Elasticsearch SKU 级搜索索引 方案

在电商系统中,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" }
    }
  }
}

关键字段说明

字段设计要点
specificationsnested 类型,支持精确匹配多个属性
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_scorefunction_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.updatedsku.stock.changed 事件。
  • 定时全量同步:每日凌晨补全数据。

2. 更新策略

  • 增量更新:使用 update API 局部更新价格、库存。
  • 全量重建: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_latencyindexing_rate
    • rejected_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 字段(如“秒杀”)
搜索去重使用 collapsespu_id 折叠
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值