在电商系统中,商品搜索是核心功能之一,而 Elasticsearch 正是构建高性能商品搜索引擎的理想选择。本文将为你详细设计一个 电商商品索引(Product Index)的完整方案,涵盖数据建模、字段设计、分片策略、搜索优化、聚合分析、生命周期管理等关键环节。
一、需求分析(电商商品搜索典型场景)
| 功能 | 说明 |
|---|---|
| 全文检索 | 支持按商品名称、品牌、描述等模糊搜索 |
| 结构化过滤 | 按类目、品牌、价格区间、库存、属性(颜色/尺寸)筛选 |
| 排序 | 综合排序、销量排序、价格排序、评分排序 |
| 聚合分析(Facets) | 展示左侧筛选面板(如“品牌”、“价格段”) |
| 高亮显示 | 搜索关键词高亮 |
| 相关性调优 | 热门商品、新品优先 |
| 数据更新频繁 | 商品信息、库存、价格实时变化 |
| 数据量大 | 百万级甚至亿级商品 |
二、索引设计方案
1. 索引命名
采用 时间+业务 命名方式,便于滚动和管理:
product-catalog-2024-10
后续可通过 ILM + Rollover 实现自动滚动。
2. 索引别名(Aliases)
使用别名实现读写分离和无缝切换:
{
"aliases": {
"product-write": { "is_write_index": true },
"product-read": {}
}
}
- 写入:
POST /product-write/_doc - 搜索:
GET /product-read/_search
3. 分片与副本设置
"settings": {
"number_of_shards": 6,
"number_of_replicas": 1,
"refresh_interval": "30s"
}
设计依据:
- 预估单索引数据量:500万商品 × 2KB ≈ 10GB
- 每 shard 控制在 10~30GB,6 分片可支撑未来增长
- 副本数 1:保证高可用和查询性能
refresh_interval: 30s:降低写入压力(商品更新非强实时)
若需近实时(如秒杀),可设为
1s。
三、Mapping 字段设计
PUT /product-catalog-2024-10
{
"settings": { ... },
"mappings": {
"dynamic": false,
"properties": {
"id": { "type": "keyword" },
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart",
"fields": {
"keyword": { "type": "keyword" }
}
},
"sub_title": { "type": "text", "analyzer": "ik_max_word" },
"brand": { "type": "keyword" },
"category_id": { "type": "keyword" },
"category_path": { "type": "keyword" }, // "1001>2003>3005"
"price": { "type": "scaled_float", "scaling_factor": 100 }, // 以分为单位存储
"original_price": { "type": "scaled_float", "scaling_factor": 100 },
"stock": { "type": "integer" },
"status": { "type": "keyword" }, // on_sale, sold_out, deleted
"sales_count": { "type": "long" },
"rating": { "type": "float" },
"tags": { "type": "keyword" }, // "新品", "爆款", "包邮"
"images": {
"type": "keyword",
"index": false // 不参与搜索,节省空间
},
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
// 商品属性(如颜色、尺寸)—— nested 类型
"attributes": {
"type": "nested",
"properties": {
"name": { "type": "keyword" }, // "颜色"
"value": { "type": "keyword" } // "红色"
}
},
// 商家信息
"shop_id": { "type": "keyword" },
"shop_name": { "type": "keyword" },
// 地理位置(支持附近门店)
"location": { "type": "geo_point" }
}
}
}
字段设计说明
| 字段 | 类型 | 说明 |
|---|---|---|
title | text + ik 分词 | 支持中文全文检索 |
title.keyword | keyword | 用于排序、聚合(如按名称排序) |
price | scaled_float | 避免 float 精度问题,scaling_factor=100 表示乘以 100 存储 |
category_path | keyword | 支持按类目层级筛选 |
attributes | nested | 支持“颜色=红色 AND 尺寸=XL”精确匹配 |
images | keyword, index: false | 仅存储,不索引,节省空间 |
tags | keyword | 用于打标和筛选 |
四、搜索查询设计
1. 全文搜索 + 过滤 + 排序
GET /product-read/_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "iPhone 手机" } }
],
"filter": [
{ "term": { "brand": "Apple" } },
{ "range": { "price": { "gte": 500000, "lte": 1000000 } } }, // 5000~10000元
{ "nested": {
"path": "attributes",
"query": {
"bool": {
"must": [
{ "match": { "attributes.name": "颜色" } },
{ "match": { "attributes.value": "红色" } }
]
}
}
}
}
]
}
},
"sort": [
{ "sales_count": { "order": "desc" } },
{ "rating": { "order": "desc" } },
{ "_score": { "order": "desc" } }
],
"highlight": {
"fields": {
"title": {}
}
}
}
2. 聚合(Facets)用于筛选面板
"aggs": {
"brands": {
"terms": { "field": "brand", "size": 10 }
},
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 100000 }, // < 1000元
{ "from": 100000, "to": 500000 },
{ "from": 500000 }
]
}
},
"colors": {
"nested": {
"path": "attributes"
},
"aggs": {
"color_values": {
"filter": { "term": { "attributes.name": "颜色" } },
"aggs": {
"values": { "terms": { "field": "attributes.value" } }
}
}
}
}
}
五、性能优化建议
1. 写入优化
- 使用
bulkAPI 批量导入商品。 - 更新时使用
updateAPI 局部更新(避免全量 reindex)。 - 设置
refresh_interval: 30s降低刷新开销。
2. 查询优化
- 过滤条件优先使用
filter(不计算评分,可缓存)。 nested查询性能较低,避免过度嵌套。- 使用
keyword字段做聚合,避免text字段fielddata。
3. 相关性调优
使用 function_score 提升热门商品权重:
"function_score": {
"query": { ... },
"functions": [
{
"field_value_factor": {
"field": "sales_count",
"factor": 0.001,
"modifier": "log1p"
}
},
{
"gauss": {
"created_at": {
"scale": "7d"
}
}
}
],
"boost_mode": "multiply"
}
六、索引生命周期管理(ILM)
1. 策略设计
PUT /_ilm/policy/product-policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": { "max_age": "30d", "max_size": "50gb" }
}
},
"warm": {
"min_age": "30d",
"actions": {
"forcemerge": { "max_num_segments": 1 },
"shrink": { "number_of_shards": 3 }
}
},
"delete": {
"min_age": "365d",
"actions": { "delete": {} }
}
}
}
}
2. 应用到模板
PUT /_index_template/product-template
{
"index_patterns": ["product-catalog-*"],
"template": {
"settings": {
"number_of_shards": 6,
"number_of_replicas": 1,
"index.lifecycle.name": "product-policy",
"index.lifecycle.rollover_alias": "product-write"
},
"mappings": { ... }
}
}
首次创建
product-catalog-000001并指向product-write别名。
七、数据同步方案
1. 同步方式
- CDC(Change Data Capture):监听 MySQL binlog(通过 Canal、Debezium)。
- MQ 消息:商品服务发送
product.updated事件到 Kafka。 - 定时 Job:每日全量同步(兜底)。
2. 更新策略
- 增量更新使用
POST /product-write/_update。 - 删除使用
POST /product-write/_delete_by_query(按 ID)。
八、高可用与监控
- 集群部署:至少 3 个节点,启用分片自动均衡。
- 监控指标:
- 索引速率(
indexing.rate) - 查询延迟(
search.latency) - JVM 内存、GC
- 分片状态(
unassigned_shards)
- 索引速率(
九、总结:电商商品索引架构图
+------------------+ +---------------------+
| MySQL / Kafka | --> | Logstash / Flink |
+------------------+ +----------+----------+
|
v
+--------------------------+
| Elasticsearch Cluster |
| |
| Index: product-catalog-* |
| Aliases: |
| - product-write |
| - product-read |
+------------+-------------+
|
v
+--------------------------+
| Kibana / App |
| Search, Filter, Facets |
+--------------------------+
十、扩展建议
- 支持多语言:使用
multi-field存储英文标题。 - 商品推荐:结合
more_like_this查询。 - 拼音搜索:使用
pinyinanalyzer 支持“iphone”搜“苹果”。 - 向量搜索:未来可接入
dense_vector实现“以图搜商品”。
构建电商商品搜索引擎的Elasticsearch方案
936

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



