索引字段说明文档
本文档详细说明了 Elasticsearch 索引中所有字段的类型、索引方式、数据来源等信息。
设计思路
- 针对店匠数据结构
- 数据源处理:时间、数值字段的规范化直接在流水线中完成,因为只有一套数据源,不需要配置化;以我们的 SPU/SKU 为标准输入。
- ES 索引方式:为了可扩展,需要定义多种索引方式,对于每个入 ES 的字段只需从中选择一种索引方式。
- 数据源处理:时间、数值字段的规范化直接在流水线中完成,因为只有一套数据源,不需要配置化;以我们的 SPU/SKU 为标准输入。
- Doc 单位为 SPU
- SKU 作为 SPU 的内部属性(ES 的 nested 结构),SKU 的价格字段展开为
min_price、max_price作为 SPU 字段。
- SKU 作为 SPU 的内部属性(ES 的 nested 结构),SKU 的价格字段展开为
- 多语言适配
- 原始数据与用户环境均为多语言,需根据语言路由到不同分析器/索引方式,在线搜索时也要考虑多语言的适配。
- 搜索接口适配
- 接口简单,自动为多语言的数据源和 query 适配最优检索策略。
- 接口简单,自动为多语言的数据源和 query 适配最优检索策略。
- 返回的结果格式约定为店匠系列的 SPU/SKU嵌套结构。
- 支撑 facet/过滤/排序业务需求:用户可以选择任何一个 keyword 或 HKText 类型的字段做筛选、聚合;也可以选择任何一个数值型字段做 Range 过滤或排序。
关键字段
参考1:spu表 & sku表 & 属性表、数据源《商品导入模板》
SPU表(shoplazza_product_spu)
主要字段:
id: BIGINT - 主键IDtenant_id: BIGINT - 租户IDhandle: VARCHAR(255) - URL handletitle: VARCHAR(512) - 商品标题brief: VARCHAR(512) - 商品简介description: TEXT - 商品描述vendor: VARCHAR(255) - 供应商/品牌category: VARCHAR(255) - 类目tags: VARCHAR(1024) - 标签seo_title: VARCHAR(512) - SEO标题seo_description: TEXT - SEO描述seo_keywords: VARCHAR(1024) - SEO关键词image_src: VARCHAR(500) - 图片URLcreate_time: DATETIME - 创建时间update_time: DATETIME - 更新时间shoplazza_created_at: DATETIME - 店匠创建时间shoplazza_updated_at: DATETIME - 店匠更新时间
spu表全部字段 "Field" "Type" "Null" "Key" "Default" "Extra" "id" "bigint(20)" "NO" "PRI" "auto_increment" "shop_id" "bigint(20)" "NO" "MUL" "" "shoplazza_id" "varchar(64)" "NO" "" "" "handle" "varchar(255)" "YES" "MUL" "" "title" "varchar(500)" "NO" "" "" "brief" "varchar(1000)" "YES" "" "" "description" "text" "YES" "" "" "spu" "varchar(100)" "YES" "" "" "vendor" "varchar(255)" "YES" "" "" "vendor_url" "varchar(500)" "YES" "" "" "seo_title" "varchar(500)" "YES" "" "" "seo_description" "text" "YES" "" "" "seo_keywords" "text" "YES" "" "" "image_src" "varchar(500)" "YES" "" "" "image_width" "int(11)" "YES" "" "" "image_height" "int(11)" "YES" "" "" "image_path" "varchar(255)" "YES" "" "" "image_alt" "varchar(500)" "YES" "" "" "inventory_policy" "varchar(50)" "YES" "" "" "inventory_quantity" "int(11)" "YES" "" "0" "" "inventory_tracking" "tinyint(1)" "YES" "" "0" "" "published" "tinyint(1)" "YES" "" "0" "" "published_at" "datetime" "YES" "MUL" "" "requires_shipping" "tinyint(1)" "YES" "" "1" "" "taxable" "tinyint(1)" "YES" "" "0" "" "fake_sales" "int(11)" "YES" "" "0" "" "display_fake_sales" "tinyint(1)" "YES" "" "0" "" "mixed_wholesale" "tinyint(1)" "YES" "" "0" "" "need_variant_image" "tinyint(1)" "YES" "" "0" "" "has_only_default_variant" "tinyint(1)" "YES" "" "0" "" "tags" "text" "YES" "" "" "note" "text" "YES" "" "" "category" "varchar(255)" "YES" "" "" "category_id" "bigint(20)" "YES" "" "" "category_google_id" "bigint(20)" "YES" "" "" "category_level" "int(11)" "YES" "" "" "category_path" "varchar(500)" "YES" "" "" "shoplazza_created_at" "datetime" "YES" "" "" "shoplazza_updated_at" "datetime" "YES" "MUL" "" "tenant_id" "bigint(20)" "NO" "MUL" "" "creator" "varchar(64)" "YES" "" "" "" "create_time" "datetime" "NO" "" "CURRENT_TIMESTAMP" "" "updater" "varchar(64)" "YES" "" "" "" "update_time" "datetime" "NO" "" "CURRENT_TIMESTAMP" "on update CURRENT_TIMESTAMP" "deleted" "bit(1)" "NO" "" "b'0'" ""
SKU表(shoplazza_product_sku)
主要字段:
id: BIGINT - 主键ID(对应variant_id)spu_id: BIGINT - SPU ID(关联字段)title: VARCHAR(500) - 变体标题price: DECIMAL(10,2) - 价格compare_at_price: DECIMAL(10,2) - 原价sku: VARCHAR(100) - SKU编码inventory_quantity: INT(11) - 库存数量option1: VARCHAR(255) - 选项1option2: VARCHAR(255) - 选项2option3: VARCHAR(255) - 选项3
sku全部字段 "Field" "Type" "Null" "Key" "Default" "Extra" "id" "bigint(20)" "NO" "PRI" "auto_increment" "spu_id" "bigint(20)" "NO" "MUL" "" "shop_id" "bigint(20)" "NO" "MUL" "" "shoplazza_id" "varchar(64)" "NO" "" "" "shoplazza_product_id" "varchar(64)" "NO" "MUL" "" "shoplazza_image_id" "varchar(64)" "YES" "" "" "title" "varchar(500)" "YES" "" "" "sku" "varchar(100)" "YES" "MUL" "" "barcode" "varchar(100)" "YES" "" "" "position" "int(11)" "YES" "" "0" "" "price" "decimal(10,2)" "YES" "" "" "compare_at_price" "decimal(10,2)" "YES" "" "" "cost_price" "decimal(10,2)" "YES" "" "" "option1" "varchar(255)" "YES" "" "" "option2" "varchar(255)" "YES" "" "" "option3" "varchar(255)" "YES" "" "" "inventory_quantity" "int(11)" "YES" "" "0" "" "weight" "decimal(10,2)" "YES" "" "" "weight_unit" "varchar(10)" "YES" "" "" "image_src" "varchar(500)" "YES" "" "" "wholesale_price" "json" "YES" "" "" "note" "text" "YES" "" "" "extend" "json" "YES" "" "" "shoplazza_created_at" "datetime" "YES" "" "" "shoplazza_updated_at" "datetime" "YES" "" "" "tenant_id" "bigint(20)" "NO" "MUL" "" "creator" "varchar(64)" "YES" "" "" "" "create_time" "datetime" "NO" "" "CURRENT_TIMESTAMP" "" "updater" "varchar(64)" "YES" "" "" "" "update_time" "datetime" "NO" "" "CURRENT_TIMESTAMP" "on update CURRENT_TIMESTAMP" "deleted" "bit(1)" "NO" "" "b'0'" ""
属性表
"id" "spu_id" "shop_id" "shoplazza_id" "shoplazza_product_id" "position" "name" "values" "tenant_id" "creator" "create_time" "updater" "update_time" "deleted" "1" "64001" "1" "7f9eaed5-ff76-4bdd-ae75-b716130e5b0d" "ef7c68fb-2685-4dc5-8996-9c32e8610499" "1" "颜色" "[""蓝色"", ""红色"", ""绿色""]" "162" "1" "16/11/2025 19:39:59" "" "18/11/2025 10:06:11" "0"
参考2:波哥 索引《店匠指南》 -> 商品详解
参考3: 店匠的商品结构 - 民丰: 固定字段: 1、必填:品名 2、非必填:副标题、类目、专辑、标签、供应商、市场
动态字段:商品属性 1、款式(一款,或者多款)这部分是可以动态自定义的 款式可以支持直接生成一个 SKU,也可以选择不启用 2、类目没有预设动态属性值,都是自定义的
我们的目标客户店匠的两个店铺,男装和女装
商品信息:品名、颜色、尺码,基本上就这三个信息
分类prefixQuery
最多三级分类,商品可以指向任何级别的分类 Field Type category varchar(255) category_id bigint(20) category_google_id bigint(20) category_level int(11) category_path varchar(500)
属性
- 组织ES输入数据的时候,需要为sku拼接spu的 option1 option2 option3,作为属性名称(比如“颜色”),sku的 option1 option2 option3 作为属性值(比如“白色”)
- 有以下方案: TODO 可以选择其中一种,或者2用于填充3用于搜索: 1)铺平展开,只支持三个,支持查询。缺点是,查询逻辑跟租户的属性维度绑定,不灵活 attr1 attr2 attr3 option1 option2 option3 2)nested,支持超过3个属性(动态)。支持查询 "specifications": { "type": "nested", "properties": { "name": { "type": "keyword" }, // "颜色", "容量" "value": { "type": "keyword" } // "白色", "256GB" } }, 3)nested,支持超过3个属性(动态)。只用作返回,不能查询。节省索引空间 "specifications": { "type": "nested", "properties": { "name": { "type": "keyword","index": false }, "value": { "type": "keyword","index": false } } },
考虑使用方案(3)。
status
- 商品下架等状态
- 无库存,是用status记录,提升查询效率
多语言
索引:中英文(两套),如果商品资料是中文,则我们系统使用 谷歌翻译(和平台使用的翻译工具对齐) 自动翻译为英文。 检索:将非中英文,翻译成英文后,再检索英文。
分面
- 分类
- 标签。这个是个扁平的结构,不是像属性那样k-v-pair的 不用考虑属性。这个 option1 2 3不能放在外面筛选。他的定位是spu内部的东西,不是外部用于筛选商品的。 即使外面要有那种 动态筛选 比如搜手机出品牌、款式 这种, 不是对应的这个字段,会是另外的字段。
字段预处理
需要用「英文逗号」隔开,作为list输入的字段: SEO关键词 专辑名称 标签 尺寸信息
SPU 与 SKU 的协同设计
参考《索引spu-sku层级结构设计.md》
rank - 相关性
rank - 提权
function_score 提升相关性
"function_score": {
"functions": [
{ "field_value_factor": { "field": "sales_count", "factor": 0.001, "modifier": "log1p" } },
{ "gauss": { "listed_at": { "scale": "30d" } } }
],
"boost_mode": "multiply"
}
索引基本信息
- 索引名称:
search_products - 索引级别: SPU级别(商品级别)
- 数据结构: SPU文档包含嵌套的skus数组
分片与副本设置
# 分片数: 根据cpu数量和sku数量决定。
"settings": {
"number_of_shards": 8,
"number_of_replicas": 1,
"refresh_interval": "15s"
}
索引类型与处理说明
文本字段
- TEXT (电商通用分析-多语言通用)
{
"type": "text",
"analyzer": "hanlp_index",
"search_analyzer": "hanlp_standard"
}
- TEXT_ZH (电商通用分析-中文)
{
"type": "text",
"analyzer": "hanlp_index",
"search_analyzer": "hanlp_standard"
}
- TEXT_EN (电商通用分析-中文)
{ "type": "text", "analyzer": "english" }
KEYWORD(关键词字段)
- ES 输入支持字符串或字符串数组,统一写入 keyword 字段,默认大小写敏感,必要时可通过 normalizer 统一大小写。
{ "type": "keyword" }
HKText(Hybrid Keyword+Text 字段)
- 该类型用于“精确匹配优先 + 模糊匹配兜底”的业务场景(如品牌、标签、SEO 关键词)。
- 典型 mapping:
{
"type": "text",
"analyzer": "factory_no_ngram_analyzer",
"search_analyzer": "factory_no_query_analyzer",
"fields": {
"keyword": { "type": "keyword", "normalizer": "lowercase" }
}
}
- 业务命名:HKText。使用
字段.keyword子字段满足过滤、聚合等精确需求,主字段支持 ngram 模糊搜索。
LONG(数值字段-整数)
{ "type": "long" }
FLOAT(数值字段-浮点数)
{ "type": "float" }
DATE(日期字段)
- 预处理:统一转换为 ISO8601(UTC)字符串或毫秒时间戳;空值保持 null。
- ES mapping:
{
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
}
- 查询:支持范围检索、排序与聚合。
TEXT_EMBEDDING(文本-多语言向量化)
- 调用“文本向量化”模块生成 1024 维向量,适用于标题、描述等语义检索场景。
{
"type": "dense_vector",
"dims": 1024,
"index": true,
"similarity": "dot_product"
}
IMAGE_EMBEDDING(图片-向量化)
- 调用“图片向量化”模块生成 1024 维向量,并保留图片 URL 以便回显。
{
"type": "nested",
"properties": {
"vector": {
"type": "dense_vector",
"dims": 1024,
"similarity": "dot_product"
},
"url": { "type": "text" }
}
}
字段说明表
基础字段
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|
| tenant_id | KEYWORD | 是 | SPU表 | tenant_id | BIGINT | BIGINT转字符串 | 租户ID,用于多租户隔离 |
| spu_id | KEYWORD | 是 | SPU表 | id | BIGINT | BIGINT转字符串 | SPU ID(主键) |
| handle | KEYWORD | 是 | SPU表 | handle | VARCHAR(255) | 商品URL handle |
数据预处理列留空表示该字段无需额外处理。
文本搜索字段
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | Boost权重 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|---|
| title | TEXT | 是 | SPU表 | title | VARCHAR(512) | 3.0 | 商品标题,权重最高 | |
| brief | TEXT | 是 | SPU表 | brief | VARCHAR(512) | 1.5 | 商品简介 | |
| description | TEXT | 是 | SPU表 | description | TEXT | 1.0 | 商品详细描述 |
SEO字段
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | Boost权重 | 是否返回 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|---|---|
| seo_title | TEXT | 是 | SPU表 | seo_title | VARCHAR(512) | 2.0 | 否 | SEO标题,用于提升相关性 | |
| seo_description | TEXT | 是 | SPU表 | seo_description | TEXT | 1.5 | 否 | SEO描述 | |
| seo_keywords | HKText | 是 | SPU表 | seo_keywords | VARCHAR(1024) | 2.0 | 否 | 按逗号分割为list,去除空白项 | SEO关键词,支持模糊匹配+精确过滤 |
分类和标签字段
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | Boost权重 | 是否返回 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|---|---|
| vendor | HKText | 是 | SPU表 | vendor | VARCHAR(255) | 1.5 | 是 | 供应商/品牌,HKText字段自动提供 vendor.keyword 用于过滤、聚合 |
|
| tags | HKText | 是 | SPU表 | tags | VARCHAR(1024) | 1.0 | 是 | 按逗号分割为list | 标签字段,支持模糊搜索;使用 tags.keyword 进行精确过滤 |
| category | HKText | 是 | SPU表 | category | VARCHAR(255) | 1.5 | 是 | 类目字段,使用 category.keyword 进行过滤/分面 |
价格字段
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|
| min_price | FLOAT | 是 | SKU表(聚合计算) | price | DECIMAL(10,2) | 聚合所有SKU最小值并转FLOAT | 最低价格(从所有SKU中取最小值) |
| max_price | FLOAT | 是 | SKU表(聚合计算) | price | DECIMAL(10,2) | 聚合所有SKU最大值并转FLOAT | 最高价格(从所有SKU中取最大值) |
| compare_at_price | FLOAT | 是 | SKU表(聚合计算) | compare_at_price | DECIMAL(10,2) | 聚合所有SKU最大值并转FLOAT | 原价(从所有SKU中取最大值) |
价格计算逻辑:
min_price: 取该SPU下所有SKU的price字段的最小值max_price: 取该SPU下所有SKU的price字段的最大值compare_at_price: 取该SPU下所有SKU的compare_at_price字段的最大值(如果存在)
图片字段
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|
| image_url | KEYWORD | 否 | SPU表 | image_src | VARCHAR(500) | 补全协议/域名,确保绝对URL | 商品主图URL,仅用于展示 |
文本嵌入字段
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|
| title_embedding | TEXT_EMBEDDING | 是 | 计算生成 | title | VARCHAR(512) | BGE-M3模型生成1024维向量 | 标题的文本向量(1024维),用于语义搜索 |
说明:
- 向量维度:1024
- 相似度算法:dot_product(点积)
- 数据来源:基于title字段通过BGE-M3模型生成
时间字段
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | 是否返回 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|---|
| create_time | DATE | 是 | SPU表 | create_time | DATETIME | 是 | 转换为UTC ISO8601字符串 | 创建时间 |
| update_time | DATE | 是 | SPU表 | update_time | DATETIME | 是 | 转换为UTC ISO8601字符串 | 更新时间 |
| shoplazza_created_at | DATE | 是 | SPU表 | shoplazza_created_at | DATETIME | 否 | 转换为UTC ISO8601字符串 | 店匠系统创建时间 |
| shoplazza_updated_at | DATE | 是 | SPU表 | shoplazza_updated_at | DATETIME | 否 | 转换为UTC ISO8601字符串 | 店匠系统更新时间 |
嵌套SKUs字段(SKU级别)
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|
| skus | JSON (nested) | 是 | SKU表 | - | - | 汇总同SPU下SKU记录,构建nested数组 | SKU数组(嵌套结构) |
SKUs子字段
| 索引字段名 | ES字段类型 | 是否索引 | 数据来源表 | 表中字段名 | 表中字段类型 | 数据预处理 | 说明 |
|---|---|---|---|---|---|---|---|
| skus.sku_id | keyword | 是 | SKU表 | id | BIGINT | BIGINT转字符串 | SKU ID |
| skus.title | text | 是 | SKU表 | title | VARCHAR(500) | SKU标题 | |
| skus.price | float | 是 | SKU表 | price | DECIMAL(10,2) | DECIMAL转FLOAT | SKU价格 |
| skus.compare_at_price | float | 是 | SKU表 | compare_at_price | DECIMAL(10,2) | DECIMAL转FLOAT | 原价 |
| skus.sku | keyword | 是 | SKU表 | sku | VARCHAR(100) | SKU编码 | |
| skus.stock | long | 是 | SKU表 | inventory_quantity | INT(11) | INT转LONG | 库存数量 |
| skus.options | object | 是 | SKU表 | option1/option2/option3 | VARCHAR(255) | 合并option1/2/3并去除空值 | 选项(颜色、尺寸等) |
Variants结构说明:
variants是一个嵌套对象数组,每个元素代表一个SKU- 使用ES的nested类型,支持对嵌套字段进行独立查询和过滤
options对象包含option1、option2、option3三个字段,分别对应SKU表中的选项值
索引配置
索引设置
- 分片数: 1
- 副本数: 0
- 刷新间隔: 30秒
查询域(Query Domains)
系统定义了多个查询域,用于在不同场景下搜索不同的字段组合:
default(默认索引): 搜索所有文本字段
- 包含字段:title, brief, description, seo_title, seo_description, seo_keywords, vendor, product_type, tags, category
- Boost: 1.0
title(标题索引): 仅搜索标题相关字段
- 包含字段:title, seo_title
- Boost: 2.0
vendor(品牌索引): 仅搜索品牌字段
- 包含字段:vendor
- Boost: 1.5
category(类目索引): 仅搜索类目字段
- 包含字段:category
- Boost: 1.5
tags(标签索引): 搜索标签和SEO关键词
- 包含字段:tags, seo_keywords
- Boost: 1.0
数据转换规则
数据类型转换
- BIGINT → KEYWORD: 数字ID转换为字符串(如
spu_id,sku_id) - DECIMAL → FLOAT: 价格字段从DECIMAL转换为FLOAT
- INT → LONG: 库存数量从INT转换为LONG
- DATETIME → DATE: 时间字段转换为ISO格式字符串
特殊处理
- 价格聚合: 从多个SKU的价格中计算min_price、max_price、compare_at_price
- 图片URL处理: 如果image_src不是完整URL,会自动添加协议前缀
- 选项合并: 将SKU表的option1、option2、option3合并为options对象
注意事项
- 多租户隔离: 所有查询必须包含
tenant_id过滤条件 - 嵌套查询: 查询variants字段时需要使用nested查询语法
- 字段命名: 用于过滤的字段应使用
*_keyword后缀的字段 - 向量搜索: title_embedding字段用于语义搜索,需要配合文本查询使用
- Boost权重: 不同字段的boost权重影响搜索结果的相关性排序
TODO
多语言问题。 店匠的products接口返回的 title tags note category seo_title seo_description 等字段,为商家销售区域所使用语言,因此英文为主,各种语言都有。 不同语言需要用不同的分析器,需要拆分不同的字段。
方案1:
索引层面: 每种文本字段,都设置多份语言索引,暂时先包括 zh en 两种即可。 以下字段做两份,如果以后对接的商家达到8种语言,那么这些字段也对应的扩展到8份。 title brief description seo_title seo_description seo_keywords vendor vendor_keyword product_type product_type_keyword category
tenant - 数据灌入: 对每个tenant设置一一个语言,作为tenant的一个基本配置。 写入索引的时候,根据语言配置将title 等文本字段写入对应的索引字段(比如 title_en) 查询的时候,将query转为商家所用语言,并到对应的field去查。
在线搜索时: 多语言搜索作为效果优化的高级特性,比如某个用户配置了 zh, en 两种语言,那么 如索引的时候会进行不全,入两个字段。 搜索的时候 也准备 query_en query_zh 两个查询词 分别到多个字段搜索。
方案2(不建议): 索引层面只要一套字段,分析器选择兼顾多种语言效果的(比如hanLP / english),两者对于中英文之外的其他语言的检索效果都会有折损。选择hanLP时 英文字段的检索质量会下降,选择English不能满足中文分词需求。