购物商城商品数据结构设计(1)——理论分析

我这里的背景是:商品量较小,例如美团,他按照店铺分类,每家店铺拥有的商品数量有限。而淘宝那种搜索一个名字可能有上万的商品的,可能就会有性能问题了。

我想到的两个可能会影响数据结构设计用户交互场景:

  1. 用户购物时商品的显示以及商品规格的选择。
  2. 商家增删改查商品时

为什么说用户交互会影响数据结构的设计,不是前端的问题吗?虽然前端可以屏蔽数据,给用户一个良好的交互,但是如果不提前考虑进去,那么后面就可能会涉及很多恶心人的数据结构的转换,才能给用户显示一个良好的交互。这个数据结构的转换,前后端都需要做。

用户购物时

购物时,首先是商品的展示,这个倒还好,后端传过来一条条商品的数据,前端展示即可。

稍微麻烦点的是商品规格的选择,我们购物时对这玩意没太大感觉,不就是选几个规格参数不就好了。比如说买个手机,通常我们要选颜色,内存和存储容量。
购物商城商品数据结构设计(1)——理论分析_第1张图片
其实这玩意还挺复杂,因为用户是不一定从上而下进行选择的,当用户随意选择了其中一个选项,比如用户先选了8GB+256G,这时候,颜色可不一定都有的选吧,有些颜色可能没有8GB+256G的,那么系统就要判断哪些颜色可以选,哪些不可以,这实际上是一个无向图,我看到有一篇文档讲的不错,可以看看

那么这跟我们的数据库的数据结构有什么关系呢?我的理解是,前端需要生成这么一个邻接矩阵(看上面那片博客的介绍),那么我们该给前端反馈一个什么的数据结构,才方便前端取生成这么一个矩阵,而不需要前端做太多数据上的解析。

如果数据库的数据不考虑存储的方式,那么我们后端就要恶心死,才能把数据整理好,发给前端。这就是我考虑的第一个点。

商品与属性,规格,库存的关系

一个型号的商品会有固定的属性和可选的属性。比如小米12pro,是一个固定的型号。它就自带了一些属性,如长宽高,重量,CPU型号等,这些属性对于这个型号而言,是固定不变的。

但是它已有一些可选的属性,如颜色,如内存大小,存储大小等。

我们对商品数据进行存储时,不同的属性是有不同的库存与售价的,如下图示意:
购物商城商品数据结构设计(1)——理论分析_第2张图片
它可以用树结构来展示效果,但是,中间的那些节点,其实没有父子关系,他们换一个顺序也完全OK。所以,树结构也不是那么完美,不过也能看出他们的关系了。

增删改查商品

一个网购商城离不开商家对货物的管理,他们需要友好的交互。

商品固有属性

那么我们在增加商品时,商家会提供商品的具体型号以及其固有的属性,假设我们用关系型数据库(mysql)去存储的话,我们是没办法把所有商品都放在一张表里的,因为这仅仅是手机的属性而已。我商城还卖洗发水吧,难道洗发水的也有CPU型号吗?

那么我们首先想到的是,每种类型的产品存一个表,分表存储,所有手机放一个表,洗发水放另一个表,确实也可以,因为对淘宝京东这样的大商场,光手机一个分类,累计几年估计也有10几万种型号,也能单独成一个表了。

但是如果我们只是一个小的不能再小的商城,几年下来估计也就卖了几十个型号的手机,但是呢,各种各样的商品都卖过,那么我们不是会有好多各种各样的表,每个表就那么几十几百条数据。这样一想,感觉不是很合理。

所以还是觉得商品得统一放到一个表里。那么一个商品的固有属性,就不能以独立的字段存在数据库了,而是使用字符串,或者直接用json类型,将商品的固有属性转换成json字符串,存到一个字段里,所以商品表的字段大概是这样:(id,所属分类,商品型号,头像,品牌,属性)。前面是商品公有的字段,属性里面就存放商品特有的字段。这样所有商品就到一个表了。

上面这种方案是有可行性的,因为固有属性是一个很少变动的属性,把它放在json中,存储方便,且 对于查询,也没问题。难的是修改,正好,他不怎么需要修改。

商品规格属性

上面只搞定了固有属性,还有可选规格属性呢。从上面图可以看出,规格属性像是树形结构,一个树形结构的数据该如何存储,才有利于增删改查呢?即使是我们规划的一个小商城,也会有大量的数据(至少是商品数量的10倍),最大的问题是,这些数据他的增删改查频率还很高:

  1. 比如,每个用户刷新一次界面,就需要查询一次商品数据
  2. 用户每购买一次商品,就需要刷新一次库存
  3. 商家实时查看商品的销量,库存等
  4. 商家随时修改商品的售价,甚至修改规格属性

然后可能也会有一些奇葩的数据统计需求,比如,商家想看手机历年来什么色系卖得好;再比如,多少毫升的洗发水最好卖。这里先不深入,我也还没想好,仅仅先把需求提出来。

关系型数据库其实是不好存储(似乎nosql更合适,如比较热门的MongoDB,但是我还没用过,不确定效果,我想应该比mysql适合)

实际上我认为规格与库存等属性的对应关系应该如下图(对比树结构少了父子关系),规格属性可以随意拓展
购物商城商品数据结构设计(1)——理论分析_第3张图片
那么我想的规格表字段大概是这样:{商品id,库存,售价,规格:{颜色,内存,存储,其他1…}}。看吧,还是一个json字符串的样子,不是关系型数据库的强项。

所以我目前的想法是:商品基础信息放在mysql上,规格库存放在nosql上。

查询商品

按照上述思路设计的话,我们现在有两个表,一个商品表,一个规格库存表。现在分析一下查询是否方便。

给用户展示商品

首要的一个场景是,如何将商品数据反馈给前端,让前端好展示。首先呢,我们得筛选出有库存的商品,没库存就不需要了。

我倾向于让前端先获取一个类别的商品。就是说,我第一步,先获取基本的商品信息用于展示给用户,而不获取规格等暂时不需要的数据。

那么只需要在商品表获取数据即可。但是这里有个问题,商品表中并没有库存信息,库存在规格表中。那么如何判断是否有库存呢?

首先,一个商品是否有库存,应该是所有规格的库存相加之和,不为0,则说明有库存。那么就可以去规格表中查一遍这个商品id下的库存之和。这样缺点是要跨表查询,有点影响质量。

我想到第二种方法是,在商品表中,新增一个库存字段,它的值等于所有规格库存的和。这样做缺点是每次更新某个规格的库存时,要同步更新这个字段。这样多少有点麻烦。

于是再改进一下,商品表中的库存字段,不存储具体的库存数量,仅表示有和没有。这样的好处是,在更新某个规格的库存时,判断一下自己的库存是否为0,不为0就不需要去更新商品表的库存了。如果为0,就去检查一下当前该商品所有规格的库存是否都为0,否则就不需要更新。同理,一个规格从0新增库存时,也要去检查这个字段。这样就大大减少了两表查询的次数了。

这样做还有个好处,因为要展示的商品是查询最频繁的数据之一,所以如果每次都去数据库查是非常低效的。放在redis才是更好的选择,这样性能大大提升,在Redis中,保存的可能是个json字符串,那么每次修改是很麻烦的事情,所以尽可能的减少修改的次数,这种方法适合这个逻辑。

PS:因为商品表的库存数量是没意义的,它不能告诉我们是哪个规格的库存。

所以,这里暂时没有大的问题

商家查询商品

商家一般关注自己有哪些商品,库存如何,销量如何,这些都好办,因为他们仅在web端展示,比用户端好办多了。

但是可能还有一些别的需求,例如:

  1. 当日销量,按销售额排序,或者按照利润率排序,按照销量排序等等,所以这些信息都得给他记录好。而且需要细致到每个规格。这里还是可以好好讲究下数据结构的设计的,因为计算量很大,搞不好的话性能会很差。因为我还没进展到这一步,所以先不拓展先,以后再来补充细节。
  2. 暂时没想到,以后补充
增加商品
用户加入购物车时

用户点击类似于“选择规格”后,就去后台查询该商品的规格,库存等。

首先,前端需要一个整体的规格信息,比如:(id:0,text:颜色,data:{红色:...;蓝色:...}),这样,前端方便生成邻接矩阵。这样还有个好处,可以将那些没有库存的规格也显示出来,只是不给选择而已。

然后呢,当用户选择了完整的规格组合之后,还得告诉用户所选的规格组合什么价钱,库存多少。所以还需要告诉前端规格组合的信息:

{商品id:001,库存:15,售价:150,规格:{颜色:红色,内存:8G,存储:64G,其他1...}}
{商品id:002,库存:16,售价:160,规格:{颜色:蓝色,内存:16G,存储:128G,其他1...}}

添加到购物车后,购物车里其实也是和商品的展示差不多,只是多了规格的信息,所以,购物车的数据结构应该是这样的:

(商品基础信息,加入购物车的数量,所选择的规格信息:{规格组合id,售价,库存,对应的规格信息:[红色,4G,128G]}

这些都可以在前面的数据中拼接出来,不需要再次去后端请求。没什么大问题。

商家增加商品

首先,商家需要先选择商品所属的分类,这样,我会提供一些一些常用的标签给商家选择,比如:商家选择在手机分类添加新的商品,那么,表单页面应该是有这些:

商品展示名,商品型号,cpu型号,屏幕大小等等,这些选项商家可以自由选择是否填写,还可以添加新的属性。

然后还有规格和库存信息,同样的,会根据之前的商品信息,给生成一个默认的表格,
在这里插入图片描述
然后用户可以自行添加,也可以删除,然后将规格信息一一添加到下方即可。

这里都问题不到,上面设计的数据结构都能满足。

但是还有个细节需要考虑一下:

商品和规格展示的顺序,这个其实很重要,用户第一眼看到商家希望被看到,对于销量是有不小的帮助的。

这里我还没想到很好的方案,后面在网上查查资料,再补充。

修改商品
用户修改购物车

修改库存和规格,这个都没什么大问题,不展开了

商家修改商品信息
  1. 修改基础信息,没什么问题
  2. 修改库存和价格,这里可能会造成用户下单了,却没有库存的问题,所以这里商家还需要有个为用户修改订单的功能。当然,需要和用户沟通。
  3. 修改规格的信息,比如“红色”不好听,改成高逼格的“深远红”装逼。首先,要去查询“深远红”是不是已经存在的规格选项,如果是,就替换成规格直接替换成这个已存在的。如果还不存在,那么新建一个“深远红”的规格,而“红色”依然保留在系统中,因为不清楚是否存在其他商品也在使用。

PS:这里我还没有完全想清楚,有点乱,后面再补充。不过问题不大的。

删除商品

没啥好说的,暂时想不到什么问题。

你可能感兴趣的:(其他,数据结构,购物商城,设计)