ES Mapping Configuration
概述
所有租户共享同一个 Elasticsearch mapping 结构。
当前目录采用“声明式 Python 规格 + 字段模板 + 最终 JSON 产物”的方式维护 search_products 的索引定义:
generate_search_products_mapping.py: 唯一的生成源,包含字段模板、语言列表、分析器配置和递归生成逻辑search_products.json: 由脚本生成的完整 ES 索引配置,包括settings和mappingssearch_suggestions.json: 搜索建议索引配置
默认应修改生成脚本中的规格定义,而不是手工编辑 search_products.json。
字段抽象
脚本从业务语义上抽象出 4 类文本模板:
all_language_text: 全语言字段,不带keywordall_language_text_with_keyword: 全语言字段,所有受支持语言都带keywordcore_language_text: 核心索引语言字段,不带keywordcore_language_text_with_keyword: 核心索引语言字段,核心语言都带keyword
这里的“核心索引语言”不是因为系统只支持两种语言,而是因为所有店铺、所有商品都必须至少产出这两种语言的索引内容。目前核心索引语言固定为:
zhen
“全语言”表示 mapping 为原始商品语言预留了更多语言槽位。商品实际灌入时,不要求每个字段把所有语言都填满,只要求:
- 核心索引语言字段必须填充
zh和en - 全语言字段必须填充
zh和en - 如果商品原始语言属于受支持语言,还应额外填充对应的原始语言字段,例如
ru
当前字段大致分为几类:
- 全语言字段:
title、keywords、brief、description、vendor、category_path、category_name_text - 核心索引语言字段:
qanchors、enriched_tags、option1_values、option2_values、option3_values、enriched_attributes.value - 复合嵌套字段:
image_embedding、specifications、enriched_attributes、skus - 其他标量字段:
tenant_id、spu_id、价格、库存、类目等
生成规则里的几个基础约束:
- 中文字段使用
index_ik,并额外设置search_analyzer: query_ik - 非中文语言使用各自的 Elasticsearch 内置 analyzer
- 带
with_keyword的模板会为对应语言增加.keyword settings.analysis、normalizer、similarity也属于生成结果的一部分,不能只维护mappings.properties
索引灌入指引
基本原则
- 所有商品都必须生成核心索引语言版本,也就是
zh和en。 - 全语言字段除了必须有
zh和en,还应尽量保留商品原始语言版本。 - 如果商品原始语言本身就是
zh或en,则原文直接写入对应字段,另一种核心语言通过翻译补齐。 - 如果商品原始语言是
ru这类受支持的非核心语言,则应同时写入原始语言字段和zh/en翻译结果。 - 如果某个值为空,不应写入伪造内容;应在上游清洗后决定是否跳过该字段。
核心索引语言字段
这类字段的目标是保证所有商品都至少能被中文和英文检索到。无论商品原始语言是什么,都应通过翻译或标准化得到 zh 和 en 两份结果。
典型字段:
qanchorsenriched_tagsoption1_valuesoption2_valuesoption3_valuesenriched_attributes.valuespecifications.value_text
以 category_path 和 option*_values 为例,核心语言灌入结果应至少包含:
category_path.zhcategory_path.enoption1_values.zhoption1_values.enoption2_values.zhoption2_values.enoption3_values.zhoption3_values.en
示例:原始商品语言为俄语,原始 option1_values 为 красный, синий
{
"option1_values": {
"zh": "红色, 蓝色",
"en": "red, blue"
}
}
示例:原始商品语言为俄语,类目路径为 Одежда > Женская одежда > Куртки
{
"category_path": {
"zh": "服饰 > 女装 > 夹克",
"en": "Apparel > Women's Clothing > Jackets",
"ru": "Одежда > Женская одежда > Куртки"
}
}
注意:category_path 在 mapping 上属于全语言字段,但在灌入规范上依然要求 zh/en 必填。
全语言字段
这类字段既要保证 zh/en 两个核心索引语言可用,也要尽量保留商品原始语言,以便原语种召回和更自然的检索。
典型字段:
titlekeywordsbriefdescriptionvendorcategory_pathcategory_name_text
灌入规则:
- 找到商品原始语言,例如
ru - 原文写入对应语言字段,例如
title.ru - 将原文翻译成
zh和en - 分别写入
title.zh和title.en
示例:原始商品语言为俄语,标题为 Женская зимняя куртка
{
"title": {
"zh": "女士冬季夹克",
"en": "Women's winter jacket",
"ru": "Женская зимняя куртка"
}
}
示例:原始商品语言为俄语,类目名称为 Женские куртки
{
"category_name_text": {
"zh": "女式夹克",
"en": "Women's jackets",
"ru": "Женские куртки"
}
}
示例:规格值 specifications.value_text / specifications.value_keyword
{
"specifications": [
{
"sku_id": "sku-red-s",
"name": "color",
"value_keyword": "красный",
"value_text": {
"zh": "红色",
"en": "red"
}
}
]
}
其中:
specifications.value_keyword保存原始规格值,用于精确过滤 / 分面specifications.value_text保存zh/en两个核心索引语言版本,用于检索召回
原始语言为中文或英文时
如果原始语言就是核心索引语言之一,不需要额外再写第三份语言字段。
示例:原始语言为中文
{
"title": {
"zh": "女士冬季夹克",
"en": "Women's winter jacket"
},
"option1_values": {
"zh": "红色, 蓝色",
"en": "red, blue"
}
}
示例:原始语言为英文
{
"title": {
"zh": "女士冬季夹克",
"en": "Women's winter jacket"
},
"vendor": {
"zh": "北境服饰",
"en": "Northern Apparel"
}
}
不同字段的灌入方式
可以按下面的方式理解和实现:
- 标量字段:直接写固定值,例如
tenant_id、spu_id、min_price - 核心索引语言字段:只生成
zh/en - 全语言字段:生成
zh/en,再按原始语言补一个对应语种字段 - 嵌套字段:对每个元素内部重复应用同样规则,例如
specifications[].value_text、enriched_attributes[].value
推荐灌入流程
- 识别商品原始语言
- 提取原文标题、描述、类目、规格、属性、选项值等字段
- 生成
zh和en两份核心索引语言内容 - 对全语言字段,如果原始语言受支持,则额外写入原始语言字段
- 组装最终 ES 文档并写入索引
生成 Mapping
在仓库根目录执行:
source activate.sh
python mappings/generate_search_products_mapping.py > mappings/search_products.json
如果只想查看输出而不覆盖文件:
source activate.sh
python mappings/generate_search_products_mapping.py
如果想先生成到临时文件:
source activate.sh
python mappings/generate_search_products_mapping.py > mappings/search_products.generated.json
校验 Mapping
确认当前 search_products.json 是否与生成规则完全一致:
source activate.sh
python mappings/generate_search_products_mapping.py --check mappings/search_products.json
创建索引
from indexer.mapping_generator import load_mapping, create_index_if_not_exists
from utils.es_client import ESClient
es_client = ESClient(hosts=["http://localhost:9200"])
mapping = load_mapping()
create_index_if_not_exists(es_client, "search_products", mapping)
修改 Mapping
推荐流程:
- 修改
mappings/generate_search_products_mapping.py - 重新生成
mappings/search_products.json - 用
--check或 diff 确认变更符合预期 - 重新创建索引并导入数据
注意:Elasticsearch 不支持直接修改已有字段的 mapping 类型,只能新增字段。如需修改字段类型,需要:
- 删除旧索引
- 使用新 mapping 创建索引
- 重新导入数据
字段说明
参考 docs/索引字段说明v2-mapping结构.md