🗂️ 为E-Commerce应用设计可扩展的分类系统

发布: (2026年2月6日 GMT+8 14:26)
5 分钟阅读
原文: Dev.to

Source: Dev.to

封面图片:🗂️ 为电子商务应用设计可扩展的分类系统

在构建电子商务应用时,分类起初看起来很简单——但当你的商品数量增长,业务需求出现以下情况时:

  • 子类别
  • 嵌套菜单
  • 面包屑导航
  • SEO友好URL
  • 轻松重新排序

本 README 说明了在真实系统中使用的可扩展、可投入生产的分类设计,且避免了过度设计。

常见错误

许多应用程序从独立的表开始:

categories
sub_categories
sub_sub_categories

当出现以下情况时,这种做法会立即失效

  • 需要更深的层级
  • 层级结构发生变化
  • 查询变得复杂

常见错误示意图

可扩展方案(单一类别表)

使用 一张表 并自引用。

CREATE TABLE categories (
    id          UUID PRIMARY KEY,          -- or BIGINT
    name        VARCHAR(255) NOT NULL,
    slug        VARCHAR(255) UNIQUE NOT NULL,
    parent_id   UUID REFERENCES categories(id),
    level       INT NOT NULL,
    path        VARCHAR(500) NOT NULL,
    sort_order  INT DEFAULT 0,
    is_active   BOOLEAN DEFAULT TRUE,
    created_at  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

这支持 无限层级嵌套 并且查询简洁。

层级工作原理

示例结构

Electronics
 └── Mobiles
      ├── Smartphones
      └── Feature Phones

存储的数据

idnameparent_idlevelpathsort_order
1电子产品NULL011
2手机111/21
3智能手机221/2/31
4功能手机221/2/42

Source:

字段拆解(重要部分)

1️⃣ slug – URL 友好的标识符

slug 是用于 URL 的可读字符串。

"Smart Phones" → "smart-phones"

使用场景:

/category/electronics/mobiles/smartphones

为什么 slug 很重要

  • 对 SEO 友好
  • 稳定的 URL
  • 不暴露内部 ID

2️⃣ level – 分类的层级深度

level 表示分类所在的层级深度。

level 0 = 根分类
level 1 = 子分类
level 2 = 子子分类

存在的原因

  • 在首页只显示顶层分类
  • 限制最大层级深度
  • 简化过滤

查询示例

SELECT * FROM categories WHERE level = 0;

3️⃣ path – 完整层级路径(物化路径)

path 保存从根节点到当前节点的 完整血缘

Electronics → Mobiles → Smartphones
path = "1/2/3"

为什么它很强大

  • 无需递归即可获取整个子树
  • 轻松构建面包屑导航
  • 生成 SEO 友好的 URL

查询示例

SELECT * FROM categories WHERE path LIKE '1/2/%';

4️⃣ sort_order – 显示顺序控制(非层级)

sort_order 决定分类在 UI 中的显示顺序。

  • 没有它 → 顺序不可预测
  • 有了它 → 业务可控制的顺序

查询示例

SELECT * FROM categories ORDER BY sort_order ASC;

使用场景

  • 导航栏排序
  • 推荐分类
  • 季节性重新排列

为什么要同时使用 level + path

用例levelpath
顶层过滤
最大深度验证
子树查询
面包屑
SEO URL

它们解决的是不同的问题,而不是重复。

产品关联

产品通常属于 叶子类别

CREATE TABLE products (
    id          UUID PRIMARY KEY,
    name        VARCHAR(255) NOT NULL,
    slug        VARCHAR(255) UNIQUE NOT NULL,
    price       NUMERIC(10,2) NOT NULL,
    category_id UUID REFERENCES categories(id)
);

最终建议

  • ✅ 单一 categories
  • parent_id 用于结构
  • level 用于深度逻辑
  • path 用于快速读取
  • slug 用于简洁 URL
  • sort_order 用于 UI 控制

此设计可从创业 MVP 扩展到大型市场而无需更改模式。

Interview One‑Liner

可扩展的分类系统使用 self‑referencing table 与 materialized paths,以支持 unlimited depth、fast reads、clean URLs 和 UI‑controlled ordering。

Back to Blog

相关文章

阅读更多 »

好代码的静默死亡

在我开始职业生涯之前,我就对编写“Good Code™”充满热情,这种热情可以追溯到我还是中学生的时候。什么是“Good Code™”…