商品表结构分析
引言
先引入两个概念:
SPU:Standard Product Unit (标准产品单位) ,一组具有共同属性的商品集
SKU:Stock Keeping Unit(库存量单位),SPU商品集因具体特性不同而细分的每个商品
- 所有sku共享的规格属性(称为全局属性)
- 每个sku不同的规格属性(称为特有属性)
1 表结构分析
手机的参数大多是颜色、版本、内存等等,而空调的参数大多都是匹数、功率等,因此设计商品参数表时不应该基于商品去设计,而应该基于商品类别去设计表结构。
所以一个分类下有一套规格参数,但是相同分类下的商品虽然规格参数相同,但是规格参数的值不同,比如都是手机,一个手机品牌参数的值是“小米”,另一个手机品牌参数的值是“苹果”。
要想简化这件事,key(参数)和值(参数的值)分开保存。key跟商品分类绑定,值跟商品绑定。比如,颜色、版本、内存等参数跟手机类别绑定,具体一个手机的品牌是什么,内存多大等值跟商品绑定。
但是也不能一个类别一张表,这样就太多了,因此这样不现实!
设计如下:
- 规格组表
tb_spec_group
:
- 规格参数表
tb_spec_param
:
通用属性
用一个布尔类型字段来标记是否为通用:
- generic来标记是否为通用属性:
- true:代表通用属性
- false:代表sku特有属性
搜索过滤
与搜索相关的有两个字段:
- searching:标记是否用作过滤
- true:用于过滤搜索
- false:不用于过滤
- segments:某些数值类型的参数,在搜索时需要按区间划分,这里提前确定好划分区间
- 比如电池容量,0-2000mAh,2000mAh-3000mAh,3000mAh-4000mAh
数值类型
某些规格参数可能为数值类型,这样的数据才需要划分区间,我们有两个字段来描述:
- numberic:是否为数值类型
- true:数值类型
- false:不是数值类型
- unit:参数的单位
2 从面向对象的角度分析
既然现在要表示规格参数的key
,暂时不考虑值,那么这些key
用java语言如何描述呢?
组该如何描述?要把组当成一类事物,对他们进行抽象,找到其中的共同特征,比如每个组都有一个名字,只不过第一个组叫 主体,第二个组叫 基本信息,以此类推,因此,组就要有一个字段叫name
来抽象表示这个组的名字,除此之外,每个组都要有一个id
。每一个组内都有很多参数,比如 主体 这一组下就有 型号、入网年份、上市年份等参数,因此还要有一个集合字段params
,存放这些参数。
注:图画的有点问题,绿色框不应该框值,应该框中间的key。
此外List<Param> params
中也可以抽象,依旧是每个参数都有name
,id
,此外还需要一个组ID来关联组表,说明这些参数是属于哪一个组下面的,这样就把group表
和param表
关联了起来。既然思考到这一步,想到互相关联,那么group表
中也可以添加一个字段categoryId
来关联商品类别。param表
中可以加入是否为数值类型的字段、该参数是否可搜索字段等等。
3 spu表的数据结构
为了不影响查询效率,基于此,我们做了表的垂直拆分,将SPU的详情放到了另一张表:tb_spu_detail
。
注:
- 垂直拆分,一张表字段过多,拆成两张表来存
- 水平拆分,一张表数据太多,拆成两张表来存
更常用的是垂直拆分,因为水平表拆分对增删改查操作很不友好,比如排序,排序只能完成一张表中数据的排序,但是现在有很多中间件来帮助实现。
根据前面的分析有:
- SPU中保存通用的规格参数信息。
- SKU中保存特有规格参数。
当时我们的规格参数表没有区分哪些是特有属性,哪些是通用属性,但还好我们的参数表中有一个字段是generic
,是一个布尔值,来表明这个参数是否为通用属性。那么我们的表该如何设计呢?
首先是generic_spec
,其中保存通用规格参数信息的值,这里为了方便查询,使用了json格式,并且跟param表一一对应(左为param表,右为generic_spec字段):
- key:对应的规格参数的
tb_spec_param
的id - value:对应规格参数的值
其次是special_spec
字段,从数据库中取一个来看:
转成json格式方便查看,如下:
- key:规格参数id
- value:spu属性的数组
那么问题来:特有规格参数应该在sku中记录才对,为什么在spu中也要记录一份?
因为我们有时候需要把所有规格参数都查询出来(比如如下商品详情界面),而不是只查询1个sku的属性。比如,商品详情页展示可选的规格参数时:
4 sku表的数据结构
sku又分成了两张表,一张tb_sku
表,一张tb_stock
表,为什么把库存单单拿出来另建一张表呢,因为一个商品读写最频繁的就是库存数据,而颜色、内存等一般不会改变,以读为主,因此我们将两张表分离,读写不会干扰。
sku表中部分字段的说明:indexes
字段:
在SPU表中,已经对特有规格参数及可选项进行了保存,结构如下:
{
"4": [
"香槟金",
"樱花粉",
"磨砂黑"
],
"12": [
"2GB",
"3GB"
],
"13": [
"16GB",
"32GB"
]
}
这些特有属性如果排列组合,会产生12个不同的SKU,而不同的SKU,其属性就是上面备选项中的一个。
比如:
- 红米4X,香槟金,2GB内存,16GB存储
- 红米4X,磨砂黑,2GB内存,32GB存储
如果我们记录下角标,就是这样:
- 红米4X,0,0,0
- 红米4X,2,0,1
既然如此,我们是不是可以将不同角标串联起来,作为spu下不同sku的标示。这就是我们的indexes字段。
这个设计在商品详情页会特别有用:
当用户点击选中一个特有属性,就能根据 角标快速定位到sku。
own_spec
字段:
看结构:
{
"4":"香槟金",
"12":"2GB",
"13":"16GB"
}
保存的是特有属性的键值对。
SPU中保存的是可选项,但不确定具体的值,而SKU中的保存的就是具体的值。
上一篇: AIX安装WebSphere后无法运行pmt.sh建立概要文件的解决方法
下一篇: 第9章 树回归