尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

电商商品三级类目体系设计:从表结构到落地实践

电商商品三级类目体系设计:从表结构到落地实践 简介面向移动端开发学习者的电商商品三级类目示例项目是一套完整的Xcode工程实现演示了在电商应用中将商品按大类、中类、小类组织并通过列表逐级展示和联动筛选。资源以zip压缩包形式提供共23个文件主要有7个源码文件、4个头文件、4个属性列表配置以及故事板界面、工程配置和测试文件等压缩包整体仅54KB结构紧凑便于快速查看与运行调试。目前已有672人学习或下载过这套资源。读者获得的是完整的工程源码包含类目数据模型、根视图和列表控制器、自定义单元格实现以及故事板构建的界面从中可以了解商品三级分类在客户端的数据组织与交互逻辑比如逐级下钻、选中回显等常见操作还能参照工程结构快速融入自己的项目。 做过电商后台或者商品系统的同学应该都听过一句话商品不上类目后面全是坑。不管是自营商城、平台电商还是给企业做ERP只要涉及商品管理就绕不开“商品三级类目”这套基础体系。很多新手刚接手时觉得它只不过是一个分类树一级、二级、三级往下挂就行了真做起来才发现类目牵一发动全身属性继承、搜索匹配、数据统计、权限控制全都挂在它上面。这篇内容我想把自己在商品中台项目里搭三级类目体系的经验完整梳理一遍讲清楚为什么是“三级”、类目与SPU/SKU怎么分工、表结构怎么设计、运营上线后有哪些坑适合正在做电商系统设计、商品域开发或者刚接手类目治理的产品经理和数据运营参考。1. 为什么是三级类目一张图看懂电商商品体系的骨架1.1 三级类目不是拍脑袋是业务与管理成本的平衡点三级类目的标准结构是一级到二级再到三级最终挂商品。比如最典型的例子“服饰”是一级类目“男装”是二级类目“T恤”是三级类目到了三级这个层级商品才能被明确归属。为什么行业里普遍默认三级而不是两级或四级这个选择背后是用户认知、管理成本和系统复杂度的三方博弈。先说两级够不够。如果类目只有两级比如“家电”下面直接挂“电视”那“电视”这个层级里会同时塞进“55寸液晶电视”“75寸OLED电视”“电视挂架”“电视音箱”前两者是电视整机后两者是完全不同的商品形态用户在前台浏览时会被大量无关商品干扰运营做活动选品时也没法快速圈定范围。再说四级行不行技术上当然可以但每深一层后台维护的复杂度、商品上架时的选择成本都会明显增加很多小类目到第四级可能只剩个位数商品管理动作却一点不少投入产出比很低。三级的合理性在于它把“行业频道—品类场景—具体商品类型”三层逻辑对齐了。一级类目对应频道和行业比如生鲜、服饰、数码二级类目对应购买场景或核心品类比如水果、男装、手机配件三级类目才是能够承载商品属性和售卖规格的最小业务单元业务上通常叫“叶子类目”。绝大多数电商平台在做GMV统计、活动招商、搜索筛选时粒度到三级就已经能回答“哪个细分类目卖得好”这类问题再往下就该是SPU和SKU的职责了。1.2 先分清类目、品牌、SPU、SKU的边界后面才不打架类目体系最容易出的问题不是表设计不出来而是业务上和品牌、SPU、SKU搅在一起。很多初期没梳理清楚的项目会出现“类目叫iPhone手机壳”“SKU叫苹果X黑色”这种命名混乱本质上就是把不同维度的概念硬塞进了同一个层级。类目解决的是“它是什么”的分类问题品牌解决的是“谁生产的”的归属问题SPU解决的是“这个商品的标准定义是什么”SKU解决的是“用户具体能买到哪种规格”。举一个生鲜的例子三级类目是“生鲜水果苹果”挂在它下面的商品是一个个SPU比如“红富士苹果”而SKU则是“红富士苹果5斤装”“红富士苹果10斤礼盒装”。你在模板属性里维护的“产地”“甜度”“果径”是类目属性它决定了SPU/SKU有哪些描述维度但属性值本身不属于类目也不属于品牌。边界清晰之后系统设计就好做了。类目表、品牌表、SPU表、SKU表各自独立通过外键关联而不是把品牌做成类目的子节点也不是把SPU名称写进类目名。类目决定“有哪些属性维度”SPU/SKU决定“具体属性值是什么”这样商品详情页的属性展示、搜索的筛选条件、运营的后台筛选全都能从一套数据模型里自动带出来而不是靠运营手工维护一份又一份的Excel映射表。2. 三级类目落地的关键设计属性继承、编码与颗粒度2.1 层级颗粒度怎么定叶子类目该细到什么程度设计类目树的第一个争论往往不是技术而是“叶子类目到底要细到什么程度”。以“男装T恤”为例有人觉得按“短袖T恤”“长袖T恤”分就够了有人坚持要按“纯棉圆领短袖T恤”再拆一层。这里我倾向于一个判断标准如果某个分类下的商品用户在做购买决策时关心的核心属性基本一致它就可以作为一个叶子类目如果需要额外若干不同属性维度才能描述清楚说明这个叶子类目还太粗需要再拆。另一个更务实的判断维度是运营需求。叶子类目会直接决定后台筛选维度、前台导航展示和搜索聚合筛选。拿“笔记本电脑”来说如果整个二级类目“电脑办公”下面直接挂所有笔记本那用户筛系统、筛显卡、筛屏幕尺寸时面对的是一堆杂乱的商品因为这部分信息属于SPU属性并没有被类目很好承接。把“笔记本轻薄本”“笔记本游戏本”作为叶子类目再在各自类目上挂属性模板运营和用户才会都觉得清爽。还要考虑非标准情况。很多系统会规定商品只能挂到叶子类目但实际中总有一些商品在二级就说不清了比如一些配件类商品。我的做法是允许“虚拟叶子节点”即在二级类目下设一个“其他”或“通用商品”的叶子层级计算上走二级类目的统计维度但商品挂载上仍然满足“必须挂在叶子类目”的约束这样既不掉数据也不破坏结构约束。2.2 属性绑定策略公共属性下放特有属性只挂在叶子三级类目真正的核心其实是属性。单纯给商品分个层级并不难难的是每个层级上挂什么属性。属性绑定的常见策略是“父类属性继承叶子类目自定义”。一级类目可以挂所有商品都有的公共属性比如品牌、是否包邮二级类目挂本品类通用的属性比如数码类的“屏幕尺寸”服饰类的“适用季节”三级叶子类目挂最细粒度的特有属性比如手机壳的“适用机型”“材质”“颜色”。属性继承有一个必须注意的细节子类目继承父类属性后可以做覆盖但不能删除。举个例子一级类目“数码”下定义了品牌属性二级“手机配件”可以继承它但为了筛选方便可能想把品牌改成“适用品牌”这是覆盖如果二级觉得数码的品牌属性没有用想要删掉这就不行了因为父层级还有其他子类目和统计口径依赖。实现上我会在属性关系表里加一个“来源层级”字段标识属性是继承的还是本层级自定义的这样运营可以看到每个属性是从哪里来的避免误删。属性还要区分“关键属性”和“普通属性”。关键属性是用户识别商品的核心维度比如手机类目的“品牌”、笔记本的“处理器型号”这类属性建议在SPU维度必须填写普通属性则允许部分为空比如“颜色”“包装清单”。关键属性会影响搜索筛选排序普通属性更多只是商品详情展示这个区分在后续做前端筛选时非常有用。2.3 类目编码规则建议用定长数字分段编码类目表的主键通常会用一个自增ID但这不代表业务编码可以省。类目编码的作用是提供稳定的、可读的、支持前缀匹配的标识。我比较推荐定长数字分段编码比如一级类目用2位二级用4位三级用6位“01”代表服饰“0101”代表男装“010101”代表T恤。编码的规律和层级结构一一对应开发在排查数据时一眼能看出商品的类目归属运营在做数据权限控制时直接按编码前缀过滤比如“0101%”就是男装全量数据。编码一旦发布就不建议变动。类目改编码会牵动商品表、日志表、订单快照等大量数据所以编码规则在设计期就要把扩展性考虑进去给一二三级各留足容量。比如一级类目2位理论上只有99个对于绝大多数业务都够了如果觉得不够可以用“两位大写字母数字”的组合但会增加录入复杂度中小规模系统没必要。排序规则也值得单独设计。后台管理树的排序、前台导航的排序、热门类目的排序建议分开维护不要用同一个order字段硬撑。更不建议运营手工维护一长串的“001,002,003”这种order值改成“list_order”同级排序和“is_hot”是否热门展示两个独立字段配合权重项比手动改排序值好用得多。3. 从零搭建三级类目体系一份直接能抄的实操流程3.1 第一步不是先建表而是先梳理商品清单很多项目一上来就画类目树画完发现跟实际商品对不上。正确做法是先拉出业务当前所有商品清单不管现在有多少把每个商品归到一个临时的最小分类里再自底向上聚合出二级和一级。这个动作看起来费时间其实是唯一能保证类目树“贴业务”的方法。实际操作时我会让商品运营、类目运营、采购如果是自营一起过会每人先认领一部分商品做归类每类商品回答两个问题用户找这类商品时习惯用什么词商品间互相区分时靠哪些关键属性。把这两个问题的答案汇总类目和属性的雏形基本就有了。比如一个做全品类的中小商城商品清单里可能有苹果、苹果手机壳、苹果笔记本电脑按物理特征分它们都带“苹果”二字但按购买决策分它们分属生鲜水果、手机配件、电脑整机三个完全不同的类目这就是类目梳理的价值切分维度必须从用户决策出发而不是从商品名称出发。类目初稿完成后需要做一次冲突评审重点检查两件事一是同一商品是否可能被同时归到两个类目下二是某个类目下是否只有一两件商品且看不到增长潜力。前者说明类目边界定义不清后者说明切分过细都应该在搭建阶段就处理掉。3.2 第二步设计类目与属性的表结构类目体系的数据模型核心是四张表类目表、属性表、属性值表、类目属性关系表。这里给一份可以直接参考的建表SQL字段我尽量精简但足够覆盖核心场景。CREATE TABLE category ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID, code varchar(16) NOT NULL COMMENT 类目编码如010101, name varchar(64) NOT NULL COMMENT 类目名称, parent_code varchar(16) NOT NULL DEFAULT COMMENT 父级编码一级类目为空, level tinyint NOT NULL DEFAULT 1 COMMENT 层级1-一级2-二级3-三级, path varchar(128) NOT NULL DEFAULT COMMENT 完整路径如010101, status tinyint NOT NULL DEFAULT 1 COMMENT 状态1-启用0-停用, list_order int NOT NULL DEFAULT 0 COMMENT 同级排序值, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_code (code), KEY idx_parent_code (parent_code), KEY idx_path (path) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT商品类目表; CREATE TABLE category_attribute ( id bigint NOT NULL AUTO_INCREMENT, category_code varchar(16) NOT NULL COMMENT 类目编码通常是叶子类目, attr_name varchar(64) NOT NULL COMMENT 属性名, attr_type tinyint NOT NULL DEFAULT 0 COMMENT 属性类型0-普通1-关键属性2-销售属性, is_key tinyint NOT NULL DEFAULT 0 COMMENT 是否关键属性, is_required tinyint NOT NULL DEFAULT 0 COMMENT 是否必填, source_level tinyint NOT NULL DEFAULT 3 COMMENT 来源层级继承或本层级定义, list_order int NOT NULL DEFAULT 0, PRIMARY KEY (id), KEY idx_category_code (category_code) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT类目属性关系表;一个容易踩坑的地方在path字段。用path冗余完整路径是为了避免递归查询但parent_code仍然要保留因为很多场景需要直接查找父级或子级只靠path做模糊查询在数据量大之后性能会变差。level字段看起来冗余但对统计口径非常关键按一级类目汇总时直接WHERE level1就能拿全量不用再处理上下级关系。属性值不建议直接以JSON塞在category_attribute表里而是单独设计attribute_value表一行一个可选项原因是JSON字段无法有效支持“按属性值筛选商品”的索引查询拆分后可以用attr_name attr_value做联合索引搜索筛选性能才有保证。3.3 第三步管理后台与对外接口的联动表格建好之后后台管理系统至少要支持三个能力类目树的增删改查、商品批量迁移类目、属性模板的绑定与调整。这三个能力实际上对应了运营日常最常用的操作路径少了任何一个后面的治理工作都会变得非常痛苦。批量迁移要特别设计。把一批商品从旧类目迁到新类目时除了改商品表里的category_code还要同步迁移商品的类目属性数据。比如“手机配件”下原来有一个“手机壳”类目现在要拆成“软壳”和“硬壳”两个叶子类目商品迁移时旧属性“材质”就要映射到新属性“外壳材质”这个映射关系需要提前在后台维护好不能靠DBA手工改库。对外接口方面最核心的接口是类目树查询和属性模板查询。类目树接口建议直接返回全量树结构并缓存属性模板接口按叶子类目编码查询返回该叶子类目继承加自定义后的完整属性列表。还有一个容易被忽略的接口是“类目链路查询”即从一个叶子类目逐级向上拿到一级、二级的名称用于商品详情页面包屑、后台编辑页回显。这个场景频率很高应该直接读缓存或者走冗余字段不要现查三张表再拼。4. 上线之后才是真正的开始类目运营与数据治理4.1 类目调整与商品迁移如何做到不影响历史数据类目树上线之后最头疼的就是类目调整。业务不断发展“手机壳”这种类目可能要从手机配件拆到数码配件或者把“电脑整机”从“电脑办公”里独立成一级类目。这时如果商品表只存了一个category_code改起来就是一条UPDATE但历史订单、历史日志里的类目信息怎么办用户之前下的订单详情页还要展示当时的类目路径如果把商品当前的类目改了历史订单就跟着错了。我的做法是双写策略商品表里的category_code是实时字段代表商品当前归属订单明细表、操作日志表里额外冗余“类目名称快照”和“类目编码快照”。也就是说在交易和日志这两个只读频次极高的场景里类目信息在下单那一刻就被冻结下来后续类目再怎么调历史数据都不受影响。实时字段负责当前的运营统计和前台展示快照字段负责历史的准确还原两边各司其职。类目调整本身也要有流程不能运营直接在后台拖拽。完整的调整应该包括先在测试环境执行一次迁移预演核对预迁移后商品数量、属性完整度、是否有商品掉到“无属性”状态确认没问题后在业务低峰期执行存量迁移迁移完成后跑一遍对账确保旧类目下商品数清零、新类目下商品数与预期一致。预演这个动作很多团队会跳过但它恰恰是避免事故的关键。4.2 叶子类目失控从“能创建”到“不许乱建”类目运营里最典型的失控场面就是叶子类目无限膨胀。今天运营小A发现“运动鞋”下面想区分跑鞋建一个“跑鞋”明天小B觉得“篮球鞋”也该单独建一个再过一阵“板鞋”“帆布鞋”都冒出来了。最后的结果是叶子类目数量几个月翻一倍大量类目下只有一两件商品前台筛选器看着琳琅满目点进去全是孤零零的几件商品用户体验非常差。这个问题本质上不是技术问题而是权限和治理问题。技术侧能做的是给叶子类目创建加审批流只有类目管理员有权限新建普通运营只能在一级、二级下申请同时设置一个“有效性检查”渲染类目树时自动统计每个叶子类目的商品数把低于阈值的叶子类目标记出来。运营侧则需要定期做类目体检建议每季度跑一次“类目健康度报表”核心指标包括“叶子类目商品数分布”“无效叶子占比”“叶子类目属性完善率”然后对低商品数类目做合并或停用处理。还有一点容易被忽略叶子类目的停用不能只改状态要处理引用关系。如果某个叶子类目下还有商品停用前必须先做商品迁移否则商品会变成“挂在停用类目下”的孤儿数据。代码里可以加一个校验禁止直接停用非空叶子类目。4.3 搜索、导航、推荐的类目依赖处理不好会伤转化类目体系不仅是后台管理的工具它直接决定前台用户的浏览和搜索体验。导航栏的一级入口通常是频道维度比如“服饰”“数码”“生鲜”点进去的左侧分类树也是按类目层级渲染的搜索结果页的筛选器则是由类目属性词驱动的。类目颗粒度如果过粗用户筛“苹果”时商品里混着苹果手机壳和苹果水果这是最典型的搜索匹配混乱场景。这里推荐两个处理手段。第一是搜索时的类目上下文识别用户搜索词命中类目名时优先展示该叶子类目下的商品比如搜“苹果”时系统分别建立“生鲜水果苹果”和“数码手机配件苹果配件”两套候选集再结合用户的历史行为判断当前意图。第二是类目加权在排序阶段对命中关键属性的商品做加权比如用户搜索“轻薄本 16G”如果商品挂在“笔记本轻薄本”下且SPU属性包含16G内存得分会明显高于未被类目正确归类但标题里硬凑关键词的商品。推荐侧也一样很多推荐系统把类目特征作为非常重要的用户偏好信号用户之前在哪个叶子类目下点击、加购最多推荐候选池就会向该类目倾斜。如果类目体系混乱推荐信号会跟着乱花了大力气做的推荐模型效果始终上不去问题往往就出在最底层的数据质量上。5. 性能优化与排查实录类目树被刷爆之后……5.1 类目树缓存设计全量缓存事件刷新类目数据本质上是低频变更、高频读取的数据非常适合做缓存。最直接的做法是把整棵类目树序列化后放到Redis里key可以叫mall:category:tree键名后面最好带一个版本号或更新时间方便排查。接口查询时先取缓存缓存缺失再查数据库并回填这是最基础的方案。但缓存有一个坑后台改了类目名或新增了一个叶子类目缓存怎么更新如果只靠过期时间比如统一设置30分钟过期那么用户看到的类目导航最长会有30分钟延迟活动上新时运营会非常不满。我的建议是基于事件刷新而不是等待过期。后台类目变更接口在事务提交之后主动发一条刷新消息或者直接删掉缓存里的类目树key让下一次请求重新加载数据库。如果系统里已经有MQ用MQ解耦会更稳因为类目变更不是一个高频操作偶尔刷慢一点问题不大。还有一个容易被忽略的点是热key问题。平时类目树接口QPS不高但大促预热阶段首页、搜索页、推荐页都会同时读类目树一个Redis key被集中打爆的教训我见过不止一次。治理方案是“本地缓存Redis二级缓存”即每个应用节点在启动时把类目树加载到本地内存Redis作为兜底后台变更通过消息通知各节点刷新本地缓存。类目树数据量通常很小几千个节点也才几百KB本地内存完全扛得住而查询性能直接从毫秒级降到微秒级。5.2 三个典型故障的排查思路速查这里把我实际遇到过的几个高频故障整理一下排查思路都经过验证遇到类似问题可以顺着这个方向走。第一个是前台类目导航显示不全。常见原因有三类缓存未刷新后台改类目后没有及时清缓存类目状态被误改为停用导致前端过滤掉了账号数据权限不足运营看到的是被裁剪后的树。排查时先看缓存时间再看库里的status字段最后确认接口有没有带权限参数三步就能定位。第二个是商品详情页的类目属性展示错乱比如一件T恤的商品详情里出现了“屏幕尺寸”这种属性。这通常是因为类目属性绑定被覆盖或商品迁移时旧属性没有正确映射到新属性。处理方式是检查商品当前category_code和SPU属性表里的属性来源看是否是从继承层级带下来的无关属性如果是历史脏数据按“商品唯一属性名唯一”做一次去重清理。第三个是按类目统计的GMV对不上。排查方向先区分“统计类目”和“成交类目”订单快照里记录的是下单时的类目实时类目可能后来被调整过两边对不上是正常的如果要口径统一就要约定报表以快照类目为准还是以当前类目为准并在报表标题上写清楚统计口径否则运营每次对数都会来投诉。故障现象常见原因排查顺序解决方案前台导航类目缺失缓存未刷新、状态停用、权限不足缓存 → 状态 → 权限事件刷新缓存检查status核对接口数据权限参数详情页属性错乱属性继承被覆盖、迁移映射错误商品类目编码 → 属性来源 → 属性映射表清理商品属性冗余重跑映射任务类目GMV不平实时类目与快照类目不一致统计口径 → 订单快照 → 类目调整记录统一报表口径历史数据重算最后再分享一个我自己的体会。商品三级类目看起来是个很底层的静态数据但它是真正“牵一发动全身”的基础工程值得产品、开发、运营三方坐在一起花时间把规则定清楚。尤其建议在系统上线前就把类目编码、属性继承、叶子类目创建权限、历史快照机制这四件事定死上线后再改每一件都是伤筋动骨的大工程。类目树没有完美的终态它一定随业务迭代但只要设计时留好了扩展位后面怎么调整都不会太痛。本文还有配套的精品资源点击获取
返回列表