在电商系统中,SKU(Stock Keeping Unit)级搜索 是比“商品级搜索”更细粒度、更贴近用户真实购买意图的高级功能。例如:
用户搜索“iPhone 15 Pro 256GB 白色”,期望直接找到具体可购买的 SKU,而不是跳转到商品详情页再选择规格。
本文将为你设计一套完整的 Elasticsearch SKU 级搜索索引方案,涵盖数据建模、字段设计、搜索逻辑、性能优化和与 SPU(标准产品单元)的协同关系。
一、背景:SPU vs SKU
| 概念 | 说明 | 示例 |
|---|---|---|
| SPU(Standard Product Unit) | 标准商品,描述产品共性 | iPhone 15 Pro |
| SKU(Stock Keeping Unit) | 库存单元,具体可售的规格 | iPhone 15 Pro 256GB 白色 |
一个 SPU 对应多个 SKU(不同颜色、容量、套餐等)。
二、SKU 搜索的核心需求
| 功能 | 说明 |
|---|---|
| 精准匹配规格 | 支持“颜色=白色 AND 容量=256GB”精确筛选 |
| 独立库存与价格 | 每个 SKU 有自己的价格、库存、编码 |
| 高亮与展示 | 搜索结果直接显示具体规格 |
| 聚合分析(Facets) | 支持按规格属性聚合(如“颜色”、“容量”) |
| 相关性排序 | 销量、评分、价格排序 |
| 去重与聚合展示 | 可选:合并相同 SPU 的 SKU 展示 |
| 高并发低延迟 | 商品详情页推荐、搜索页筛选 |
三、索引设计方案
1. 索引命名
采用时间序列 + 业务命名:
sku-catalog-2024-10
后续通过 ILM + Rollover 实现自动滚动。
2. 索引别名(Aliases)
实现读写分离:
{
"aliases": {
"sku-write": { "is_write_index": true },
"sku-read": {}
}
}
- 写入:
POST /sku-write/_doc - 搜索:
GET /sku-read/_search
3. 分片与副本设置
"settings": {
"number_of_shards": 8,
"number_of_replicas": 1,
"refresh_interval": "15s"
}
设计依据:
- SKU 数量通常是 SPU 的 3~10 倍,数据量更大。
refresh_interval: 15s:SKU 价格/库存更新较频繁,需较快可见。- 8 分片:支持千万级 SKU(每 shard 100200 万文档)。
四、Mapping 字段设计
PUT /sku-catalog-2024-10
{
"settings": { ... },
"mappings": {
"dynamic": false,
"properties": {
"id": { "type": "keyword" }, // SKU ID
"spu_id": { "type": "keyword" }, // 关联 SPU
"title": { // 搜索主字段
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart",
"fields": {
"keyword": { "type": "keyword" } // 用于排序
}
},
"full_title": { // 完整标题(含规格)
"type": "text",
"analyzer": "ik_max_word"
},
"brand": { "type": "keyword" },
"category_path": { "type": "keyword" }, // 类目路径
"price": { "type": "scaled_float", "scaling_factor": 100 }, // 单位:分
"original_price": { "type": "scaled_float", "scaling_factor": 100 },
"stock": { "type": "integer" },
"status": { "type": "keyword" }, // in_stock, out_of_stock, deleted
"sales_count": { "type": "long" },
"rating": { "type": "float" },
"tags": { "type": "keyword" }, // "限时折扣", "包邮"
// 规格属性(核心字段)—— nested 类型
"specifications": {
"type": "nested",
"properties": {
"name": { "type": "keyword" }, // "颜色", "容量"
"value": { "type": "keyword" }, // "白色", "256GB"
"sort_order": { "type": "integer" } // 排序权重
}
},
// 图片与视频(不索引)
"image_url": { "type": "keyword", "index": false },
"video_url": { "type": "keyword", "index": false },
// 商家与店铺
"shop_id": { "type": "keyword" },
"shop_name": { "type": "keyword" },
// 条形码 / SKU 编码
"sku_code": { "type": "keyword" }, // 用于扫码搜索
// 上下架时间
"listed_at": { "type": "date" },
"delisted_at": { "type": "date" }
}
}
}
关键字段说明
| 字段 | 设计要点 |
|---|---|
specifications | nested 类型,支持精确匹配多个属性 |
full_title | 包含规格的完整标题,如“iPhone 15 Pro 256GB 白色”,提升搜索命中率 |
sku_code | 支持扫码或手动输入 SKU 编码搜索 |
price, stock | 实时性要求高,需快速同步 |
status | 过滤已下架或无库存 SKU |
五、搜索查询设计
1. 全文搜索 + 规格过滤
GET /sku-read/_search
{
"query": {
"bool": {
"must": [
{ "match": { "full_title": "iPhone 15 Pro 白色 256GB" } }
],
"filter": [
{ "term": { "status": "in_stock" } },
{ "range": { "price": { "lte": 900000 } } }, // ≤ 9000元
{ "nested": {
"path": "specifications",
"query": {
"bool": {
"must": [
{ "match": { "specifications.name": "颜色" } },
{ "match": { "specifications.value": "白色" } }
]
}
}
}
},
{ "nested": {
"path": "specifications",
"query": {
"bool": {
"must": [
{ "match": { "specifications.name": "容量" } },
{ "match": { "specifications.value": "256GB" } }
]
}
}
}
}
]
}
},
"sort": [
{ "sales_count": { "order": "desc" } },
{ "price": { "order": "asc" } }
],
"highlight": {
"fields": {
"full_title": {}
}
}
}
2. 聚合(Facets)用于规格筛选面板
"aggs": {
"colors": {
"nested": { "path": "specifications" },
"aggs": {
"color_filter": {
"filter": { "term": { "specifications.name": "颜色" } },
"aggs": {
"values": { "terms": { "field": "specifications.value" } }
}
}
}
},
"capacities": {
"nested": { "path": "specifications" },
"aggs": {
"capacity_filter": {
"filter": { "term": { "specifications.name": "容量" } },
"aggs": {
"values": { "terms": { "field": "specifications.value" } }
}
}
}
},
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 500000 },
{ "from": 500000, "to": 800000 },
{ "from": 800000 }
]
}
}
}
六、性能优化策略
1. nested 查询优化
nested查询性能较低,建议:- 将常用规格(如颜色、容量)冗余为独立字段(denormalization):
"color": { "type": "keyword" },
"capacity": { "type": "keyword" }
- 查询时优先用
term过滤,nested仅用于复杂组合。
2. 冗余字段示例(推荐)
"properties": {
"color": { "type": "keyword" },
"capacity": { "type": "keyword" },
"network": { "type": "keyword" },
"edition": { "type": "keyword" }
}
写入时从
specifications提取并填充这些字段,提升查询性能。
3. 使用 script_score 或 function_score 提升相关性
"function_score": {
"functions": [
{ "field_value_factor": { "field": "sales_count", "factor": 0.001, "modifier": "log1p" } },
{ "gauss": { "listed_at": { "scale": "30d" } } }
],
"boost_mode": "multiply"
}
七、SPU 与 SKU 的协同设计
方案一:独立索引(推荐)
spu-catalog-*:用于品牌、类目、商品介绍等宏观搜索。sku-catalog-*:用于具体规格搜索、下单。
优势:职责分离,查询更高效。
方案二:联合查询
GET /spu-read,sku-read/_search
适用于“模糊搜索 → 跳转详情页”的场景。
方案三:父子文档(不推荐)
join类型维护 SPU-SKU 关系。- 性能差,维护复杂,不适用于高并发搜索场景。
八、数据同步方案
1. 同步来源
- MySQL 商品库:通过 CDC(Debezium/Canal)监听
sku表变更。 - MQ 事件:商品服务发布
sku.updated、sku.stock.changed事件。 - 定时全量同步:每日凌晨补全数据。
2. 更新策略
- 增量更新:使用
updateAPI 局部更新价格、库存。 - 全量重建:SPU 信息变更时,重新生成所有 SKU 文档。
九、索引生命周期管理(ILM)
PUT /_ilm/policy/sku-policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": { "max_age": "30d", "max_size": "50gb" }
}
},
"warm": {
"min_age": "30d",
"actions": {
"forcemerge": { "max_num_segments": 1 }
}
},
"delete": {
"min_age": "730d", // 保留两年
"actions": { "delete": {} }
}
}
}
}
应用到模板,自动滚动。
十、高可用与监控
- 副本数 ≥ 1:保证节点故障时查询可用。
- 监控重点:
query_latency、indexing_raterejected_threads(线程池拒绝)nested query性能JVM heap usage
十一、总结:SKU 搜索架构图
+------------------+ +---------------------+
| MySQL (SKU 表) | --> | Debezium / Kafka |
+------------------+ +----------+----------+
|
v
+--------------------------+
| Elasticsearch Cluster |
| |
| Index: sku-catalog-* |
| - nested specifications|
| - 冗余字段(color等) |
| Aliases: sku-read/write |
+------------+-------------+
|
v
+--------------------------+
| App / Mini Program |
| 搜索“白色 256GB” → 直达SKU |
+--------------------------+
十二、扩展建议
| 场景 | 建议方案 |
|---|---|
| 扫码搜 SKU | 使用 term 查询 sku_code |
| 以图搜 SKU | 结合 dense_vector 向量字段 |
| 库存强一致 | 查询时调用实时库存服务校验 |
| 促销标签 | 动态注入 tags 字段(如“秒杀”) |
| 搜索去重 | 使用 collapse 按 spu_id 折叠 |
556

被折叠的 条评论
为什么被折叠?



