# 索引字段说明文档

> 历史版本说明：本文件为 v1 归档文档，部分模型与实现细节（如 BGE-M3）已过时。当前以 `docs/索引字段说明v2.md` 与 `docs/向量化模块和API说明文档.md` 为准。

本文档详细说明了 Elasticsearch 索引中所有字段的类型、索引方式、数据来源等信息。

## 设计思路

1. **针对店匠数据结构**  
 - 数据源处理：时间、数值字段的规范化直接在流水线中完成，因为只有一套数据源，不需要配置化；以我们的 SPU/SKU 为标准输入。  
 - ES 索引方式：为了可扩展，需要定义多种索引方式，对于每个入 ES 的字段只需从中选择一种索引方式。
2. **Doc 单位为 SPU**  
 - SKU 作为 SPU 的内部属性（ES 的 nested 结构），SKU 的价格字段展开为 `min_price`、`max_price` 作为 SPU 字段。
3. **多语言适配**  
 - 原始数据与用户环境均为多语言，需根据语言路由到不同分析器/索引方式，在线搜索时也要考虑多语言的适配。
4. **搜索接口适配**  
 - 接口简单，自动为多语言的数据源和 query 适配最优检索策略。  
- 返回的结果格式约定为店匠系列的 SPU/SKU嵌套结构。  
 - 支撑 facet/过滤/排序业务需求：用户可以选择任何一个 keyword 或 HKText 类型的字段做筛选、聚合；也可以选择任何一个数值型字段做 Range 过滤或排序。

## 关键字段

参考1：spu表 & sku表 & 属性表、数据源《商品导入模板》
### SPU表（shoplazza_product_spu）
主要字段：
- `id`: BIGINT - 主键ID
- `tenant_id`: BIGINT - 租户ID
- `handle`: VARCHAR(255) - URL handle
- `title`: 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) - 图片URL
- `create_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) - 选项1
- `option2`: VARCHAR(255) - 选项2
- `option3`: 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)


### 属性
1. 组织ES输入数据的时候，需要为sku拼接spu的 option1 option2 option3，作为属性名称（比如“颜色”），sku的 option1 option2 option3 作为属性值（比如“白色”）
2. 有以下方案： 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
1. 商品下架等状态
2. 无库存，是用status记录，提升查询效率

### 多语言
索引：中英文（两套），如果商品资料是中文，则我们系统使用 谷歌翻译（和平台使用的翻译工具对齐） 自动翻译为英文。
检索：将非中英文，翻译成英文后，再检索英文。

## 分面
1. 分类
2. 标签。这个是个扁平的结构，不是像属性那样k-v-pair的
不用考虑属性。这个 option1 2 3不能放在外面筛选。他的定位是spu内部的东西，不是外部用于筛选商品的。  即使外面要有那种 动态筛选 比如搜手机出品牌、款式 这种， 不是对应的这个字段，会是另外的字段。


### 字段预处理
需要用「英文逗号」隔开，作为list输入的字段：
SEO关键词
专辑名称
标签
尺寸信息


## SPU 与 SKU 的协同设计

参考《索引spu-sku层级结构设计.md》


## rank - 相关性


## rank - 提权

function_score 提升相关性
```json
"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数组


## 分片与副本设置
```json
# 分片数： 根据cpu数量和sku数量决定。
"settings": {
  "number_of_shards": 8,
  "number_of_replicas": 1,
  "refresh_interval": "15s"
}
```

## 索引类型与处理说明

### 文本字段

- **TEXT**  (电商通用分析-多语言通用)

  ```json
  {
    "type": "text",
    "analyzer": "hanlp_index",
    "search_analyzer": "hanlp_standard"
  }
  ```

- **TEXT_ZH**  (电商通用分析-中文)

  ```json
  {
    "type": "text",
    "analyzer": "hanlp_index",
    "search_analyzer": "hanlp_standard"
  }
  ```

- **TEXT_EN** (电商通用分析-中文)

  ```json
  { "type": "text", "analyzer": "english" }
  ```

### KEYWORD（关键词字段）

- ES 输入支持字符串或字符串数组，统一写入 keyword 字段，默认大小写敏感，必要时可通过 normalizer 统一大小写。  

  ```json
  { "type": "keyword" }
  ```

### HKText（Hybrid Keyword+Text 字段）

- 该类型用于“精确匹配优先 + 模糊匹配兜底”的业务场景（如品牌、标签、SEO 关键词）。  
- 典型 mapping：  

  ```json
  {
    "type": "text",
    "analyzer": "factory_no_ngram_analyzer",
    "search_analyzer": "factory_no_query_analyzer",
    "fields": {
      "keyword": { "type": "keyword", "normalizer": "lowercase" }
    }
  }
  ```
- 业务命名：**HKText**。使用 `字段.keyword` 子字段满足过滤、聚合等精确需求，主字段支持 ngram 模糊搜索。

### LONG（数值字段-整数）

```json
{ "type": "long" }
```

### FLOAT（数值字段-浮点数）

```json
{ "type": "float" }
```

### DATE（日期字段）

- 预处理：统一转换为 ISO8601（UTC）字符串或毫秒时间戳；空值保持 null。  
- ES mapping：
  
  ```json
  {
    "type": "date",
    "format": "strict_date_optional_time||epoch_millis"
  }
  ```
- 查询：支持范围检索、排序与聚合。

### TEXT_EMBEDDING（文本-多语言向量化）

- 调用“文本向量化”模块生成 1024 维向量，适用于标题、描述等语义检索场景。  

  ```json
  {
    "type": "dense_vector",
    "dims": 1024,
    "index": true,
    "similarity": "dot_product"
  }
  ```

### IMAGE_EMBEDDING（图片-向量化）

- 调用“图片向量化”模块生成 1024 维向量，并保留图片 URL 以便回显。  

  ```json
  {
    "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）

系统定义了多个查询域，用于在不同场景下搜索不同的字段组合：

1. **default（默认索引）**: 搜索所有文本字段
   - 包含字段：title, brief, description, seo_title, seo_description, seo_keywords, vendor, product_type, tags, category
   - Boost: 1.0

2. **title（标题索引）**: 仅搜索标题相关字段
   - 包含字段：title, seo_title
   - Boost: 2.0

3. **vendor（品牌索引）**: 仅搜索品牌字段
   - 包含字段：vendor
   - Boost: 1.5

4. **category（类目索引）**: 仅搜索类目字段
   - 包含字段：category
   - Boost: 1.5

5. **tags（标签索引）**: 搜索标签和SEO关键词
   - 包含字段：tags, seo_keywords
   - Boost: 1.0

## 数据转换规则

### 数据类型转换

1. **BIGINT → KEYWORD**: 数字ID转换为字符串（如 `spu_id`, `sku_id`）
2. **DECIMAL → FLOAT**: 价格字段从DECIMAL转换为FLOAT
3. **INT → LONG**: 库存数量从INT转换为LONG
4. **DATETIME → DATE**: 时间字段转换为ISO格式字符串

### 特殊处理

1. **价格聚合**: 从多个SKU的价格中计算min_price、max_price、compare_at_price
2. **图片URL处理**: 如果image_src不是完整URL，会自动添加协议前缀
3. **选项合并**: 将SKU表的option1、option2、option3合并为options对象

## 注意事项

1. **多租户隔离**: 所有查询必须包含 `tenant_id` 过滤条件
2. **嵌套查询**: 查询variants字段时需要使用nested查询语法
3. **字段命名**: 用于过滤的字段应使用 `*_keyword` 后缀的字段
4. **向量搜索**: title_embedding字段用于语义搜索，需要配合文本查询使用
5. **Boost权重**: 不同字段的boost权重影响搜索结果的相关性排序


## TODO
多语言问题。
店匠的products接口返回的 title tags note category  seo_title seo_description 等字段，为商家销售区域所使用语言，因此英文为主，各种语言都有。
不同语言需要用不同的分析器，需要拆分不同的字段。

方案1：
1. 索引层面：
每种文本字段，都设置多份语言索引，暂时先包括 zh en 两种即可。
以下字段做两份，如果以后对接的商家达到8种语言，那么这些字段也对应的扩展到8份。
title brief description seo_title seo_description seo_keywords vendor vendor_keyword product_type product_type_keyword category


2. tenant - 数据灌入：
对每个tenant设置一一个语言，作为tenant的一个基本配置。
写入索引的时候，根据语言配置将title 等文本字段写入对应的索引字段（比如 title.en）
查询的时候，将query转为商家所用语言，并到对应的field去查。


3. 在线搜索时：
多语言搜索作为效果优化的高级特性，比如某个用户配置了 zh, en 两种语言，那么 如索引的时候会进行不全，入两个字段。
搜索的时候 也准备 query_en query_zh 两个查询词 分别到多个字段搜索。


方案2（不建议）：
索引层面只要一套字段，分析器选择兼顾多种语言效果的（比如hanLP / english），两者对于中英文之外的其他语言的检索效果都会有折损。选择hanLP时 英文字段的检索质量会下降，选择English不能满足中文分词需求。
