--- title: "Easysearch 的推荐方案 text / keyword 怎么选?" date: 2026-02-10 lastmod: 2026-02-10 description: "深入讲解 Easysearch 字段类型选型策略,详解 Text 与 Keyword 的底层区别、应用场景、优缺点及陷阱,介绍 Multi-fields 多字段设计模式,结合 ZSTD 压缩优势提供最佳实践决策流程。" tags: ["字段类型", "Mapping设计", "Multi-fields"] summary: "在设计 Easysearch 的索引 Mapping 时,开发者面临的第一个也是最高频的灵魂拷问就是: “这个字段,我到底该设为 text 还是 keyword?” 选错了会有什么后果? 选了 text:无法排序,无法聚合,或者聚合报错 Fielddata is disabled。 选了 keyword:搜“手机”搜不到“苹果手机”,大小写必须完全一致。 本文将深入剖析这两种类型的底层区别,并给出 Easysearch 环境下的最佳选型策略。 1. 一图看懂核心区别 # 特性 Keyword (精确值) Text (全文本) 处理方式 原样存储。不分词,不转换大小写。 分词处理。经过 Analyzer 拆分成词项 (Token)。 典型场景 状态码、ID、标签、邮箱、URL、品牌名。 文章正文、商品描述、日志消息内容。 主要用途 精确过滤 (term)、排序、聚合 (Aggs)。 全文检索 (match)、模糊匹配。 底层结构 倒排索引 + Doc Values (列式存储)。 倒排索引 (Inverted Index)。 能否聚合 ✅ 非常快 (基于磁盘)。 ❌ 默认禁用 (需开启 Fielddata,极耗内存)。 2." --- 在设计 Easysearch 的索引 Mapping 时,开发者面临的第一个也是最高频的灵魂拷问就是: **“这个字段,我到底该设为 **`text`** 还是 **`keyword`**?”** 选错了会有什么后果? - 选了 `text`:无法排序,无法聚合,或者聚合报错 `Fielddata is disabled`。 - 选了 `keyword`:搜“手机”搜不到“苹果手机”,大小写必须完全一致。 本文将深入剖析这两种类型的底层区别,并给出 Easysearch 环境下的最佳选型策略。 --- ## 1. 一图看懂核心区别 | 特性 | **Keyword (精确值)** | **Text (全文本)** | | :----------- | :------------------------------------- | :----------------------------------------------- | | **处理方式** | **原样存储**。不分词,不转换大小写。 | **分词处理**。经过 Analyzer 拆分成词项 (Token)。 | | **典型场景** | 状态码、ID、标签、邮箱、URL、品牌名。 | 文章正文、商品描述、日志消息内容。 | | **主要用途** | 精确过滤 (`term`)、排序、聚合 (Aggs)。 | 全文检索 (`match`)、模糊匹配。 | | **底层结构** | 倒排索引 + **Doc Values** (列式存储)。 | **倒排索引** (Inverted Index)。 | | **能否聚合** | ✅ 非常快 (基于磁盘)。 | ❌ 默认禁用 (需开启 Fielddata,极耗内存)。 | --- ## 2. 深入剖析:Keyword (精确与统计之王) **Keyword** 是结构化数据的首选。如果你拿到一个字符串,心里想的是:“我以后要用这个值来分组统计”或者“我要精确查找这个特定值”,那么请毫不犹豫选择 `keyword`。 ### 2.1 什么时候选 Keyword? - **枚举值**:Status (`"Active"`, `"Closed"`), Gender (`"M"`, `"F"`). - **唯一标识**:User ID, Order ID, UUID, IP 地址。 - **短文本标签**:Product Tag (`"New Arrival"`), Category. - **需要排序/聚合**:按价格排序、按品牌分组统计销量。 ### 2.2 陷阱提示 `keyword` 是**大小写敏感**的! - 数据存入 `"Apple"`。 - 搜索 `term: "apple"` -> **搜不到**。 - 搜索 `term: "Apple"` -> **搜到了**。 **解决方案**:如果你需要“精确匹配但不区分大小写”,可以使用 `normalizer` 将 keyword 统一转为小写存储。 --- ## 3. 深入剖析:Text (智能搜索的核心) **Text** 是非结构化数据的归宿。它存在的意义就是为了被“拆解”,以便让人通过搜索其中的一部分词语找到整个文档。 ### 3.1 什么时候选 Text? - **长文本**:博客文章、新闻内容、备注信息。 - **自然语言**:用户评论、即时通讯消息。 - **混合搜索**:比如地址(“北京市朝阳区...”),你希望搜“朝阳”能命中。 ### 3.2 陷阱提示 千万不要尝试在 `text` 字段上开启 `fielddata: true` 来强行做聚合。 - 这会将庞大的倒排索引加载到 JVM 堆内存中。 - **后果**:极易引发 **OOM (Out Of Memory)**,导致节点崩溃。 --- ## 4. 最佳实践:成年人不做选择,我全都要 (Multi-fields) 在实际业务中,我们经常遇到这种需求: > “标题字段 (`title`),我既想通过关键词搜到它,又想按标题字母顺序排序。” 这时候,**多字段(Multi-fields)** 是标准解决方案。我们在 Mapping 中定义一个主字段为 `text`,并在其下定义一个子字段为 `keyword`。 ### 4.1 Mapping 配置示例 ```json # 1. 主字段:用于全文搜索 (match) # 2. 子字段:名字叫 raw (也可以叫 keyword) # 3. 超过 256 字符的被截断(不索引该子字段) PUT /products { "mappings": { "properties": { "title": { "type": "text", "analyzer": "ik_max_word", "fields": { "raw": { "type": "keyword", "ignore_above": 256 } } } } } } ``` ### 4.2 如何使用? - **搜索时**:用 `title`。 ```json "match": { "title": "华为手机" } ``` - **排序/聚合时**:用 `title.raw`。 ```json "sort": [ { "title.raw": "asc" } ] ``` --- ## 5. Easysearch 独家优势:ZSTD 压缩让“全都要”更轻松 在传统的 Elasticsearch 中,使用 Multi-fields 策略最大的痛点是**存储膨胀**。同一个字符串被存了两份(一份分词,一份原样),索引大小会显著增加。 但在 **INFINI Easysearch** 中,这一顾虑被大大减轻: - **ZSTD 压缩**:Easysearch 支持 `ZSTD` 算法。 - **收益**:对于重复度高的 Keyword 数据,ZSTD 能够提供极高的压缩比。这意味着,**你在 Easysearch 中使用 **`text`** + **`keyword`** 双字段策略的磁盘成本,可能比其他引擎只存单字段的成本还要低。** 因此,在 Easysearch 中,我们**强烈推荐**对于不确定的短文本字段(如标题、姓名、文件名),默认采用 **Text + Keyword** 的组合方式。 --- ## 6. 决策流程图 (Cheat Sheet) 当你拿到一个新字段时,请按此流程决策: 1. **这是一段很长的文字(如文章正文)吗?** - 是 -> 选 **Text**。 - 否 -> 进入下一步。 2. **我需要对它进行全文检索(搜中间的词)吗?** - 不需要(只搜完全匹配)-> 选 **Keyword**。 - 需要 -> 进入下一步。 3. **我需要对它进行排序或聚合(统计)吗?** - 不需要 -> 选 **Text**。 - 需要 -> 选 **Text + Keyword (Multi-fields)**。 ## 总结 - **Keyword** 是给机器看的,用于过滤和统计,快准狠。 - **Text** 是给人看的,用于模糊搜索,理解语义。 - **Multi-fields** 是万能钥匙,能同时满足搜索和统计需求。 - 利用 Easysearch 的 **ZSTD 压缩** 能力,你可以更大胆地使用 Multi-fields 而无需过分担心存储成本。