电商网站,商品规格的设计思路 |
您所在的位置:网站首页 › 相信爱情百度百科女主 › 电商网站,商品规格的设计思路 |
1.商品规格数据结构
如图,这是一个商品详情页,它包括商品名称、价格、描述、规格等等数据信息。我们应该如何把这些数据存储到数据库,如何设计数据模型,是一个很关键的问题。如果设计的不好,会大大增加开发、运营、维护的成本。 首先,我们需要知道,这些参数不能存在一张表里,因为 每个商品 的规格参数不同,一个商品的每个规格的价格、名字等参数都不同。一个商品和该商品的所有规格是一对多的关系,所以要分成多个表存储。 1.1.SPU和SKU为了更准确描述商品及细分差别,抽象出两个概念:SPU和SKU,了解一下: SPU:Standard Product Unit (标准产品单位) ,一组具有共同属性的商品集 就比如说是,上图的Iphone11,就是一个spu(它不是一个商品,而是一组),是一组有共同属性的商品,它们的共同属性就是,它们都叫Iphone11。(比如,Iphone11有金色、银色、有256G、64G。所以Iphone是一组商品。) SPU是一个抽象的商品集概念,为了方便后台的管理。 SKU:Stock Keeping Unit(库存量单位),SPU商品集因具体特性不同而细分的每个商品 SKU才是具体要销售的商品,每一个SKU的价格、库存可能会不一样,用户购买的是SKU而不是SPU 比如说,绿色的、64G、优惠套装1的Iphone11就是一个sku。把所有规格参数,排列组合组成了一个商品集spu。一个sku才是一个具体的商品,仔细数数还是很多的。 所以不要以为1个商品存起来很简单。 1.2.数据库设计分析 1.2.1.思考并发现问题弄清楚了SPU和SKU的概念区分,接下来我们一起思考一下该如何设计数据库表。 首先来看SPU,SPU的表应该有哪些字段来描述? id:主键 title:标题 description:描述 specification:规格 packaging_list:包装 after_service:售后服务 comment:评价 category_id:商品分类 brand_id:品牌 spu里都是某个商品集里所有商品的相同点,比如名称都叫Iphone11、商品分类、品牌也都一样。
再看下SKU应该有的数据库字段 id:主键 spu_id:关联的spu price:价格 images:图片 stock:库存 颜色? 内存? 硬盘? 除了上面的所有商品都有的规格参数(如,id,spu_id,price等),不同的商品种类还会有它独特的参数,比如,手机有内存大小、衣服有尺码大小等等,这些独特的规格参数该如何解决? 其实颜色、内存、硬盘属性都是规格参数中的字段。所以,要解决这个问题,首先要能清楚规格参数。 1.2.2.分析规格参数仔细查看每一种商品的规格你会发现: 虽然商品规格千变万化,但是同一类商品(如手机)的规格是统一的,比如说,所有手机都有 品牌、内存、型号、长度、宽度、重量、操作系统等等参数。在搜索商品时,通常也会有按商品种类搜索的功能。 比如这种搜索。 1.2.3.SKU的特有属性SKU中会有一些特殊属性,用来区分不同的SKU,我们称为SKU特有属性。如Iphone11的颜色、内存属性。 不同种类的商品,一个手机,一个衣服,其SKU属性不相同。 同一种类的商品,比如都是衣服,SKU属性基本是一样的,都是颜色、尺码等。 这样说起来,似乎SKU的特有属性也是与分类相关的?事实上,仔细观察你会发现,SKU的特有属性是商品规格参数的一部分。 也就是说,我们没必要单独对SKU的特有属性进行设计,它可以看做是规格参数中的一部分。这样规格参数中的属性可以标记成两部分: spu下所有sku共享的规格属性(称为全局属性)每个sku不同的规格属性(称为特有属性) 1.2.4.搜索属性过滤条件中的屏幕尺寸、运行内存、网路、机身内存、电池容量、CPU核数等,在规格参数中都能找到 。 也就是说,规格参数中的数据,将来会有一部分作为搜索条件来使用。我们可以在设计时,将这部分属性标记出来,将来做搜索的时候,作为过滤条件。要注意的是,无论是SPU的全局属性,还是SKU的特有属性,都有可能作为搜索过滤条件的,并不冲突,而是有一个交集: 1.3.规格参数表 1.3.1.表结构规格参数的格式: 可以看到规格参数是分组的,每一组都有多个参数键值对。不过对于规格参数的模板而言,其值现在是不确定的,不同的商品值肯定不同,模板中只要保存组信息、组内参数信息即可。 因此我们设计了两张表: tb_spec_group:组,与商品分类关联tb_spec_param:参数名,与组关联,一对多 1.3.2.规格组规格参数分组表:tb_spec_group 规格组有3个字段: id:主键cid:商品分类id,一个分类下有多个模板name:该规格组的名称。 1.3.2.规格参数规格参数表:tb_spec_param 按道理来说,我们的规格参数就只需要记录参数名、组id、商品分类id即可。但是这里却多出了很多字段,为什么? 还记得我们之前的分析吧,规格参数中有一部分是 SKU的通用属性,一部分是SKU的特有属性,而且其中会有一些将来用作搜索过滤,这些信息都需要标记出来。 1.通用属性 generic来标记是否为通用属性: true:代表通用属性 false:代表sku特有属性
2.搜索过滤 与搜索相关的有两个字段: searching:标记是否用作过滤 true:用于过滤搜索 false:不用于过滤 segments:某些数值类型的参数,在搜索时需要按区间划分,这里提前确定好划分区间比如电池容量,0~2000mAh,2000mAh~3000mAh,3000mAh~4000mAh 3.数值类型 某些规格参数可能为数值类型,这样的数据才需要划分区间,我们有两个字段来描述: numberic:是否为数值类型 true:数值类型 false:不是数值类型 unit:参数的单位 3.SPU和SKU数据结构规格确定以后,就可以添加商品了,先看下SPU和SKU的数据库表 3.1.SPU表CREATE TABLE `tb_spu` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'spu id', `title` varchar(255) NOT NULL DEFAULT '' COMMENT '标题', `sub_title` varchar(255) DEFAULT '' COMMENT '子标题', `cid1` bigint(20) NOT NULL COMMENT '1级类目id', `cid2` bigint(20) NOT NULL COMMENT '2级类目id', `cid3` bigint(20) NOT NULL COMMENT '3级类目id', `brand_id` bigint(20) NOT NULL COMMENT '商品所属品牌id', `saleable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否上架,0下架,1上架', `valid` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否有效,0已删除,1有效', `create_time` datetime DEFAULT NULL COMMENT '添加时间', `last_update_time` datetime DEFAULT NULL COMMENT '最后修改时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=208 DEFAULT CHARSET=utf8 COMMENT='spu表,该表描述的是一个抽象的商品,比如 iphone8'; 与我们前面分析的基本类似,但是似乎少了一些字段,比如商品描述。 我们做了表的垂直拆分,将SPU的详情放到了另一张表:tb_spu_detail CREATE TABLE `tb_spu_detail` ( `spu_id` bigint(20) NOT NULL, `description` text COMMENT '商品描述信息', `generic_spec` varchar(10000) NOT NULL DEFAULT '' COMMENT '通用规格参数数据', `special_spec` varchar(1000) NOT NULL COMMENT '特有规格参数及可选值信息,json格式', `packing_list` varchar(3000) DEFAULT '' COMMENT '包装清单', `after_service` varchar(3000) DEFAULT '' COMMENT '售后服务', PRIMARY KEY (`spu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 这张表中的数据都比较大,为了不影响主表的查询效率我们拆分出这张表。 需要注意的是这两个字段:generic_spec和special_spec。 规格参数与商品分类绑定,一个分类下的所有SPU具有类似的规格参数。SPU下的SKU可能会有不同的规格参数信息,因此我们计划是这样: SPUDetail中保存通用的规格参数信息。 SKU中保存特有规格参数。 来看下我们的表如何存储这些信息。 3.1.1.generic_spec字段首先是generic_spec,其中保存通用规格参数信息的值,这里为了方便查询,使用了json格式: json结构,其中都是键值对: key:对应的规格参数的spec_param的id value:对应规格参数的值 3.1.2.special_spec字段我们说spu中只保存通用规格参数,那么为什么有多出了一个special_spec字段呢? 以手机为例,品牌、操作系统等肯定是全局通用属性,内存、颜色等肯定是特有属性。 当你确定了一个SPU,比如小米的:红米4X 全局属性值都是固定的了: 品牌:小米 型号:红米4X 特有属性举例: 颜色:[香槟金, 樱花粉, 磨砂黑] 内存:[2G, 3G] 机身存储:[16GB, 32GB] 颜色、内存、机身存储,作为SKU特有属性,key虽然一样,但是SPU下的每一个SKU,其值都不一样,所以值会有很多,形成数组。 我们在SPU中,会把特有属性的所有值都记录下来,形成一个数组。 里面又有哪些内容呢? 来看数据格式: 也是json结构: key:规格参数id value:spu属性的数组 那么问题来:特有规格参数应该在sku中记录才对,为什么在spu中也要记录一份? 因为我们有时候需要把所有规格参数都查询出来,而不是只查询1个sku的属性。比如,商品详情页展示可选的规格参数时:
刚好符合我们的结构,这样页面渲染就非常方便了。 3.2.SKU表CREATE TABLE `tb_sku` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'sku id', `spu_id` bigint(20) NOT NULL COMMENT 'spu id', `title` varchar(255) NOT NULL COMMENT '商品标题', `images` varchar(1000) DEFAULT '' COMMENT '商品的图片,多个图片以‘,’分割', `price` bigint(15) NOT NULL DEFAULT '0' COMMENT '销售价格,单位为分', `indexes` varchar(100) COMMENT '特有规格属性在spu属性模板中的对应下标组合', `own_spec` varchar(1000) COMMENT 'sku的特有规格参数,json格式', `enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否有效,0无效,1有效', `create_time` datetime NOT NULL COMMENT '添加时间', `last_update_time` datetime NOT NULL COMMENT '最后修改时间', PRIMARY KEY (`id`), KEY `key_spu_id` (`spu_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='sku表,该表表示具体的商品实体,如黑色的64GB的iphone 8'; 还有一张表,代表库存: CREATE TABLE `tb_stock` ( `sku_id` bigint(20) NOT NULL COMMENT '库存对应的商品sku id', `seckill_stock` int(9) DEFAULT '0' COMMENT '可秒杀库存', `seckill_total` int(9) DEFAULT '0' COMMENT '秒杀总数量', `stock` int(9) NOT NULL COMMENT '库存数量', PRIMARY KEY (`sku_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='库存表,代表库存,秒杀库存等信息'; 问题:为什么要将库存独立一张表? 因为库存字段写频率较高,而SKU的其它字段以读为主,因此我们将两张表分离,读写不会干扰。 特别需要注意的是sku表中的indexes字段和own_spec字段。sku中应该保存特有规格参数的值,就在这两个字段中。 3.2.1.indexes字段在SPU表中,已经对特有规格参数及可选项进行了保存,结构如下: { "4": [ "香槟金", "樱花粉", "磨砂黑" ], "12": [ "2GB", "3GB" ], "13": [ "16GB", "32GB" ] } 这些特有属性如果排列组合,会产生12个不同的SKU,而不同的SKU,其属性就是上面备选项中的一个。 比如: 红米4X,香槟金,2GB内存,16GB存储 红米4X,磨砂黑,2GB内存,32GB存储 你会发现,每一个属性值,对应于SPUoptions数组的一个选项,如果我们记录下角标,就是这样: 红米4X,0,0,0 红米4X,2,0,1 既然如此,我们是不是可以将不同角标串联起来,作为SPU下不同SKU的标示。这就是我们的indexes字段。 这个设计在商品详情页会特别有用: 当用户点击选中一个特有属性,你就能根据 角标快速定位到sku。 3.2.2.own_spec字段看结构:
{"4":"香槟金","12":"2GB","13":"16GB"} 保存的是特有属性的键值对。 SPU中保存的是可选项,但不确定具体的值,而SKU中的保存的就是具体的值。 4.整体表结构 整体的表结构非常复杂。最好分开来看,平时开发时,也都是开发某个模块,也就涉及其中的几张表,只要把这几张表的关系捋清楚就行了。 1.品牌和spu的关系是1对多,一个品牌有多个spu,比如说品牌苹果,下面有IPhone6、Iphone7。 2.分类和spu也是1对多,比如,分类手机,下面有Iphone6、Iphone7。搜索时,需要直接从分类查找该分类下的spu。 3.spu和sku的关系是1对多,比如,Iphone6下有Iphone6(银色,16G)。
4.规格组(spec_group)合规格参数(spec_param)的关系是1对多,比如规格组的主体对应参数 品牌、型号。规格组的 基本信息 对应 参数 机身颜色、机身重量(g)、机身材质工艺。 5.分类(category)和参数组是1对多。分类和规格参数也是一对多,之所以分类和规格参数、规格参数组关联,就是为了搜索的时候用到。用户选中一个分类(比如说:手机),然后根据手机这个分类的参数组和规格参数搜索到合适的手机。规格参数组里的searching字段就是判断,该参数是不是用于搜索的。
6.规格参数表里还有一个generic字段,判断该字段是否是通用字段,如果是,那就是该spu下所有sku都相同的参数。该参数就会以特定json格式(格式就是 规格参数id:唯一的值)存在spu_detail里;如果不是通用字段,会以json格式(格式就是 规格参数id:所有可能的值的数组)存储在spu_detail表里。
7.sku表里的own_spec表存的是该sku所有特有参数的键值对,indexs存的是它所有特定参数的值在spu_detail表里special_param字段的json数组的下表。 4.1表展示1.spec_group 规格参数组 表 2.spec_param 规格参数 表 3.sku表 4.spu表 5.spu_detail表 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |