一、分词器基础概念
1.1 什么是分词器(Analyzer)?
分词器是 Elasticsearch 中将文本转换为索引词(Term)的核心组件。它决定了文本如何被切分、处理和存储,直接影响搜索的准确性和效率。
核心作用:
示例 1: Standard Analyzer (默认分词器)
原始文本:
"The Quick Brown Fox jumps over the lazy dog!"
经过 standard analyzer 处理后:
["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
// 仅转小写和分词,不做词干提取
示例 2: English Analyzer (带词干提取和停用词过滤)
原始文本:
"The Quick Brown Fox jumps over the lazy dog!"
经过 english analyzer 处理后:
["quick", "brown", "fox", "jump", "lazi", "dog"]
// "the", "over" 被停用词过滤移除
// "jumps" → "jump", "lazy" → "lazi" (词干提取)
1.2 分词发生的时机
分词在两个关键时刻发生:
(1)索引时分词(Index Time)
json
PUT /my_index/_doc/1
{
"title": "Elasticsearch 分词器原理"
}
// 写入时使用 analyzer 进行分词
(2)搜索时分词(Search Time)
json
GET /my_index/_search
{
"query": {
"match": {
"title": "分词器" // 搜索时也需要分词
}
}
}
重要原则: 索引时和搜索时的分词器应保持一致,否则可能导致搜不到结果。
二、分词器工作原理
2.1 分词器的三大组件
Elasticsearch 分词器由三部分组成,按顺序执行:
原始文本
↓
【Character Filters】字符过滤器(0个或多个)
↓
【Tokenizer】分词器(有且仅有1个)
↓
【Token Filters】词元过滤器(0个或多个)
↓
最终 Terms
2.2 组件详解
(1)Character Filters - 字符过滤器
作用: 在分词前对原始文本进行预处理
内置 Character Filters:
| 过滤器 | 功能 | 示例 |
|---|---|---|
| html_strip | 去除 HTML 标签 | <p>Hello</p> → Hello |
| mapping | 字符映射替换 | & → and |
| pattern_replace | 正则表达式替换 | 123-456 → 123_456 |
示例:
json
POST /_analyze
{
"char_filter": ["html_strip"],
"text": "<p>This is a <b>test</b></p>"
}
// 结果:This is a test
(2)Tokenizer - 分词器(核心)
作用: 将文本切分成词元(Token)
常见 Tokenizer:
| 分词器 | 分词规则 | 适用场景 |
|---|---|---|
| standard | 按空格、标点分词 | 英文通用 |
| whitespace | 仅按空格分词 | 简单场景 |
| keyword | 不分词,整体作为一个词 | 精确匹配 |
| pattern | 正则表达式分词 | 自定义规则 |
| ik_max_word | 最细粒度分词 | 中文索引 |
| ik_smart | 智能分词 | 中文搜索 |
示例对比:
原始文本: "user-123@example.com"
standard tokenizer:
["user", "123", "example.com"]
whitespace tokenizer:
["user-123@example.com"]
pattern tokenizer (按 - 和 @ 分割):
["user", "123", "example.com"]
(3)Token Filters - 词元过滤器
作用: 对分词后的词元进行增删改
常见 Token Filters:
| 过滤器 | 功能 | 示例 |
|---|---|---|
| lowercase | 转小写 | Hello → hello |
| uppercase | 转大写 | hello → HELLO |
| stop | 删除停用词 | 去除 the、a、an |
| synonym | 同义词替换 | quick → fast |
| stemmer | 词干提取 | jumping → jump |
| ngram | N-Gram 切分 | hello → he, el, ll, lo |
| edge_ngram | 边界 N-Gram | hello → h, he, hel, hell |
示例:
json
POST /_analyze
{
"tokenizer": "standard",
"filter": ["lowercase", "stop"],
"text": "The Quick Brown Fox"
}
// 结果:["quick", "brown", "fox"]
// "the" 被 stop filter 移除
2.3 完整分词流程示例
json
// 方法1: 使用内置 char_filter
POST /_analyze
{
"char_filter": ["html_strip"],
"tokenizer": "standard",
"filter": ["lowercase", "stop"],
"text": "<p>Tom & Jerry</p> are FRIENDS!"
}
// 方法2: 自定义 char_filter (需先定义索引)
PUT /test_index
{
"settings": {
"analysis": {
"char_filter": {
"my_char_filter": {
"type": "mapping",
"mappings": ["& => and"]
}
},
"analyzer": {
"my_analyzer": {
"char_filter": ["my_char_filter"],
"tokenizer": "standard",
"filter": ["lowercase", "stop"]
}
}
}
}
}
POST /test_index/_analyze
{
"analyzer": "my_analyzer",
"text": "Tom & Jerry are FRIENDS!"
}
处理流程:
Step 1: Character Filter
"Tom & Jerry are FRIENDS!"
↓ mapping: & => and
"Tom and Jerry are FRIENDS!"
Step 2: Tokenizer (standard)
↓
["Tom", "and", "Jerry", "are", "FRIENDS"]
Step 3: Token Filters
↓ lowercase
["tom", "and", "jerry", "are", "friends"]
↓ stop (移除 "and", "are")
["tom", "jerry", "friends"]
三、内置分词器详解
3.1 Standard Analyzer(标准分词器)
特点: Elasticsearch 默认分词器,适用于大多数西文语言
组成:
- Tokenizer:
standard - Filter:
lowercase
注 : 默认不包含 stop filter。如需停用词过滤,应使用 stop analyzer 或自定义配置。
分词示例:
json
POST /_analyze
{
"analyzer": "standard",
"text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
// 结果:
["the", "2", "quick", "brown", "foxes", "jumped", "over", "the", "lazy", "dog's", "bone"]
适用场景:
- 英文文本索引
- 多语言混合文本
- 默认选择
局限性:
- 中文支持差(单字分词)
- 不支持词干提取
3.2 Simple Analyzer(简单分词器)
特点: 按非字母字符分词,并转小写
组成:
- Tokenizer:
lowercase(同时完成分词和转小写)
分词示例:
json
POST /_analyze
{
"analyzer": "simple",
"text": "The 2 QUICK Brown-Foxes jumped!"
}
// 结果:
["the", "quick", "brown", "foxes", "jumped"]
// 注意:数字 "2" 被移除
适用场景:
- 纯字母文本
- 不需要保留数字的场景
对比 Standard:
| 文本 | Standard | Simple |
|---|---|---|
| "user-123" | ["user", "123"] | ["user"] |
| "HTTP/2.0" | ["http", "2.0"] | ["http"] |
3.3 Whitespace Analyzer(空格分词器)
特点: 仅按空格分词,不做任何其他处理
组成:
- Tokenizer:
whitespace
分词示例:
json
POST /_analyze
{
"analyzer": "whitespace",
"text": "The QUICK Brown-Fox jumped!"
}
// 结果:
["The", "QUICK", "Brown-Fox", "jumped!"]
// 保留大小写和标点
适用场景:
- 日志分析(保留原始格式)
- 代码索引
- 需要保留大小写的场景
3.4 Stop Analyzer(停用词分词器)
特点: Simple Analyzer + 停用词过滤
组成:
- Tokenizer:
lowercase - Filter:
stop
分词示例:
json
POST /_analyze
{
"analyzer": "stop",
"text": "The quick brown fox jumps over the lazy dog"
}
// 结果:
["quick", "brown", "fox", "jumps", "lazy", "dog"]
// 移除了 "the", "over"
默认英文停用词:
a, an, and, are, as, at, be, but, by, for, if, in, into, is, it,
no, not, of, on, or, such, that, the, their, then, there, these,
they, this, to, was, will, with
适用场景:
- 全文搜索(提高相关性)
- 减少索引大小
3.5 Keyword Analyzer(关键词分词器)
特点: 不分词,整体作为一个词元
组成:
- Tokenizer:
keyword
分词示例:
json
POST /_analyze
{
"analyzer": "keyword",
"text": "The Quick Brown Fox"
}
// 结果:
["The Quick Brown Fox"]
// 整个文本作为一个词
适用场景:
- 邮箱地址
- 状态码(如 "SUCCESS", "FAILED")
- ID、标签
- 精确匹配字段
Mapping 配置:
json
PUT /my_index
{
"mappings": {
"properties": {
"email": {
"type": "keyword" // 等同于使用 keyword analyzer
},
"status": {
"type": "keyword"
}
}
}
}
3.6 Pattern Analyzer(正则分词器)
特点: 使用正则表达式分词
默认配置:
- Pattern:
\W+(非单词字符) - Filter:
lowercase
分词示例:
json
POST /_analyze
{
"analyzer": "pattern",
"text": "The foo_bar_123 test"
}
// 结果:
["the", "foo_bar_123", "test"]
自定义 Pattern:
json
PUT /my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_email_analyzer": {
"type": "pattern",
"pattern": "[@.]", // 按 @ 和 . 分词
"lowercase": true
}
}
}
}
}
// 测试:
POST /my_index/_analyze
{
"analyzer": "my_email_analyzer",
"text": "john.doe@example.com"
}
// 结果:["john", "doe", "example", "com"]
适用场景:
- 结构化数据(日志、路径)
- 自定义分词规则
3.7 Language Analyzers(语言分词器)
支持的语言: Elasticsearch 内置 30+ 种语言分词器
常见语言分词器:
| 分词器 | 语言 | 特性 |
|---|---|---|
| english | 英语 | 词干提取、停用词 |
| french | 法语 | 法语停用词、词干 |
| german | 德语 | 德语停用词、词干 |
| spanish | 西班牙语 | 西语停用词、词干 |
| arabic | 阿拉伯语 | 阿语词干、归一化 |
English Analyzer 示例:
json
POST /_analyze
{
"analyzer": "english",
"text": "The dogs are running quickly"
}
// 结果:
["dog", "run", "quick"]
// dogs → dog (复数处理)
// running → run (词干提取)
// quickly → quick (副词处理)
// "the", "are" 被停用词过滤
词干提取对比:
| 原词 | 词干 |
|---|---|
| running | run |
| runs | run |
| ran | ran |
| dogs | dog |
| easily | easili |
| walking | walk |
注 : 词干提取使用的是 Porter Stemming 算法,某些词干看起来不是完整单词(如 easili),这是正常现象。词干提取的目的是将词归一化,而非生成有意义的单词。
适用场景:
- 英文全文搜索
- 提高召回率(searching 能匹配 search)
3.8 Fingerprint Analyzer(指纹分词器)
特点: 用于去重和聚类,生成文本指纹
处理流程:
- 转小写
- 移除扩展字符
- 排序
- 去重
- 连接成单个词元
分词示例:
json
POST /_analyze
{
"analyzer": "fingerprint",
"text": "The Quick Brown Fox jumped over the quick dog"
}
// 结果:
["brown dog fox jumped over quick the"]
// 排序 + 去重("quick" 只保留一次)
适用场景:
- 数据去重
- 文档指纹生成
- 相似性检测
四、中文分词器
4.1 为什么需要中文分词器?
中文特点:
- 没有天然的词边界(不像英文有空格)
- 一词多义、同音异义现象严重
- 新词出现快(网络用语、专业术语)
Standard Analyzer 对中文的处理:
json
POST /_analyze
{
"analyzer": "standard",
"text": "我爱北京天安门"
}
// 结果:
["我", "爱", "北", "京", "天", "安", "门"]
// 单字分词,无法识别 "北京"、"天安门"
4.2 IK 分词器(最流行)
安装:
bash
# 安装 IK 分词器 (版本需与 Elasticsearch 版本一致)
# 示例: Elasticsearch 8.11.0 → elasticsearch-analysis-ik-8.11.0
bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.11.0/elasticsearch-analysis-ik-8.11.0.zip
# 或使用在线安装 (自动匹配版本,需配置镜像源)
bin/elasticsearch-plugin install analysis-ik
# 安装后需要重启 Elasticsearch
两种分词模式:
(1)ik_max_word - 最细粒度分词
特点: 穷尽所有可能的分词组合
json
POST /_analyze
{
"analyzer": "ik_max_word",
"text": "中华人民共和国国歌"
}
// 结果:
["中华人民共和国", "中华人民", "中华", "华人", "人民共和国", "人民", "共和国", "共和", "国国", "国歌"]
适用场景:
- 索引时使用(建立更多索引词,提高召回率)
- 需要细粒度匹配
(2)ik_smart - 智能分词
特点: 粗粒度分词,最少切分
json
POST /_analyze
{
"analyzer": "ik_smart",
"text": "中华人民共和国国歌"
}
// 结果:
["中华人民共和国", "国歌"]
适用场景:
- 搜索时使用(减少干扰)
- 需要语义完整性
典型配置:
json
PUT /my_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word", // 索引时细粒度
"search_analyzer": "ik_smart" // 搜索时粗粒度
}
}
}
}
自定义词典:
# config/analysis-ik/custom.dic
知乎
CSDN
Elasticsearch
微服务
容器化
配置文件:
xml
<!-- config/analysis-ik/IKAnalyzer.cfg.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="ext_dict">custom.dic</entry>
<entry key="ext_stopwords">stopword.dic</entry>
</properties>
4.3 jieba 分词器
特点: Python jieba 的 Elasticsearch 实现
安装:
bash
bin/elasticsearch-plugin install https://github.com/sing1ee/elasticsearch-jieba-plugin/releases/download/v8.x.x/elasticsearch-jieba-plugin-8.x.x.zip
分词示例:
json
POST /_analyze
{
"analyzer": "jieba_index",
"text": "我来到北京清华大学"
}
// 结果:
["我", "来到", "北京", "清华大学", "清华", "华大", "大学"]
优势:
- 新词识别能力强
- 支持自定义词典
- Python 生态兼容性好
4.4 HanLP 分词器
特点: 基于 HanLP(汉语言处理包),自然语言处理能力强
分词示例:
json
POST /_analyze
{
"analyzer": "hanlp",
"text": "乒乓球拍卖完了"
}
// 结果(智能识别歧义):
["乒乓球", "拍卖", "完", "了"]
// 而不是 ["乒乓球拍", "卖完", "了"]
高级功能:
- 命名实体识别(NER)
- 词性标注
- 关键词提取
- 依存句法分析
4.5 中文分词器对比
| 分词器 | 速度 | 准确性 | 新词识别 | 自定义词典 | 推荐场景 |
|---|---|---|---|---|---|
| IK | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ✅ | 通用场景 |
| jieba | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ✅ | 新词多的场景 |
| HanLP | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ✅ | NLP 深度场景 |
五、自定义分词器
5.1 自定义分词器结构
json
PUT /my_index
{
"settings": {
"analysis": {
"char_filter": {
// 自定义字符过滤器
},
"tokenizer": {
// 自定义分词器
},
"filter": {
// 自定义词元过滤器
},
"analyzer": {
// 组合以上组件
}
}
}
}
5.2 实战案例 1:邮箱分词器
需求: 将邮箱拆分为用户名、域名等部分
json
PUT /email_index
{
"settings": {
"analysis": {
"tokenizer": {
"email_tokenizer": {
"type": "pattern",
"pattern": "[@.]" // 按 @ 和 . 分割
}
},
"analyzer": {
"email_analyzer": {
"tokenizer": "email_tokenizer",
"filter": ["lowercase"]
}
}
}
}
}
// 测试:
POST /email_index/_analyze
{
"analyzer": "email_analyzer",
"text": "John.Doe@Example.COM"
}
// 结果:
["john", "doe", "example", "com"]
5.3 实战案例 2:同义词分词器
需求: 搜索 "快速" 也能匹配 "迅速"
Step 1:创建同义词文件
# config/analysis/synonym.txt
快速, 迅速, 高速
手机, 电话
购买, 买
Step 2:配置分词器
json
PUT /product_index
{
"settings": {
"analysis": {
"filter": {
"my_synonym_filter": {
"type": "synonym",
"synonyms_path": "analysis/synonym.txt" // 同义词文件路径
}
},
"analyzer": {
"ik_syno": {
"tokenizer": "ik_smart",
"filter": ["my_synonym_filter"]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_syno"
}
}
}
}
测试:
json
// 索引文档
PUT /product_index/_doc/1
{"title": "快速充电手机"}
// 搜索 "迅速" 也能匹配
GET /product_index/_search
{
"query": {
"match": {"title": "迅速"}
}
}
// 能找到文档 1
同义词配置重要说明:
-
索引时 vs 搜索时:
- 推荐仅在搜索时使用同义词(避免索引膨胀)
- 特殊场景可在索引时使用
-
同义词格式:
# 格式1: 同义词组(双向替换) 快速, 迅速, 高速 # 格式2: 单向映射(仅将右侧映射到左侧) 迅速, 高速 => 快速 -
热更新:
- 修改同义词文件后需要关闭并重新打开索引
- 或使用
_reload_search_analyzersAPI (Elasticsearch 7.3+)
jsonPOST /my_index/_reload_search_analyzers -
性能影响:
- 同义词过多会影响查询性能
- 建议控制在每组 3-5 个同义词以内
5.4 实战案例 3:拼音分词器
需求: 支持拼音搜索(搜索 "zhongguo" 匹配 "中国")
安装插件:
bash
bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-pinyin/releases/download/v8.x.x/elasticsearch-analysis-pinyin-8.x.x.zip
配置:
json
PUT /pinyin_index
{
"settings": {
"analysis": {
"analyzer": {
"ik_pinyin_analyzer": {
"type": "custom",
"tokenizer": "ik_smart",
"filter": ["my_pinyin", "lowercase"]
}
},
"filter": {
"my_pinyin": {
"type": "pinyin",
"keep_first_letter": true, // 保留首字母:zgr
"keep_separate_first_letter": false,
"keep_full_pinyin": true, // 保留全拼:zhong guo ren
"keep_original": true, // 保留原文
"limit_first_letter_length": 16,
"lowercase": true
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "ik_pinyin_analyzer",
"search_analyzer": "ik_smart" // ⚠️ 重要: 搜索时不使用拼音
}
}
}
}
**重要说明**:
- 索引时使用拼音分词器,生成拼音索引
- 搜索时不使用拼音分词器,避免误匹配
- 原因:如果搜索时也分词为拼音,"张三"会匹配所有 zs 开头的名字
测试:
json
POST /pinyin_index/_analyze
{
"analyzer": "ik_pinyin_analyzer",
"text": "中国人"
}
// 结果:
["中国人", "zhong", "guo", "ren", "zgr"]
// 索引文档
PUT /pinyin_index/_doc/1
{"name": "中国"}
// 拼音搜索
GET /pinyin_index/_search
{
"query": {"match": {"name": "zhongguo"}}
}
// 能匹配到 "中国"
5.5 实战案例 4:N-Gram 分词器
需求: 支持模糊搜索和前缀匹配
Edge N-Gram vs N-Gram:
原文: "hello"
N-Gram (min=2, max=3):
["he", "hel", "el", "ell", "ll", "llo", "lo"]
Edge N-Gram (min=2, max=5):
["he", "hel", "hell", "hello"] // 仅从开头切分
配置:
json
PUT /autocomplete_index
{
"settings": {
"analysis": {
"tokenizer": {
"my_edge_ngram": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 10,
"token_chars": ["letter", "digit"]
}
},
"analyzer": {
"autocomplete_analyzer": {
"tokenizer": "my_edge_ngram",
"filter": ["lowercase"]
},
"autocomplete_search_analyzer": {
"tokenizer": "standard",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "autocomplete_analyzer",
"search_analyzer": "autocomplete_search_analyzer"
}
}
}
}
测试:
json
// 索引
PUT /autocomplete_index/_doc/1
{"title": "Elasticsearch"}
// 搜索 "elas" 能匹配
GET /autocomplete_index/_search
{
"query": {"match": {"title": "elas"}}
}
适用场景:
- 搜索框自动补全
- 前缀匹配
- 容错搜索
六、分词器使用场景
6.1 场景对比表
| 场景 | 推荐分词器 | 原因 |
|---|---|---|
| 英文全文搜索 | english / standard |
词干提取,停用词过滤 |
| 中文全文搜索 | ik_max_word + ik_smart |
索引细粒度,搜索粗粒度 |
| 电商商品搜索 | ik_max_word + 同义词 |
提高召回率 |
| 日志分析 | whitespace / pattern |
保留原始格式 |
| 邮箱、URL | keyword / 自定义 pattern |
精确匹配或结构化分词 |
| 用户名搜索 | edge_ngram |
前缀匹配 |
| 拼音搜索 | pinyin + ik |
支持拼音输入 |
| 代码搜索 | whitespace / keyword |
保留大小写和符号 |
| 多语言混合 | standard + icu_analyzer |
Unicode 规范化 |
6.2 典型应用案例
案例 1:电商平台商品搜索
json
PUT /products
{
"settings": {
"analysis": {
"filter": {
"product_synonym": {
"type": "synonym",
"synonyms": [
"手机, 电话, 移动电话",
"笔记本, 电脑, laptop",
"充电器, 充电宝"
]
}
},
"analyzer": {
"product_index_analyzer": {
"tokenizer": "ik_max_word",
"filter": ["lowercase", "product_synonym"]
},
"product_search_analyzer": {
"tokenizer": "ik_smart",
"filter": ["lowercase", "product_synonym"]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "product_index_analyzer",
"search_analyzer": "product_search_analyzer",
"fields": {
"pinyin": {
"type": "text",
"analyzer": "pinyin"
}
}
},
"brand": {
"type": "keyword" // 品牌精确匹配
}
}
}
}
案例 2:日志检索系统
json
PUT /logs
{
"settings": {
"analysis": {
"tokenizer": {
"log_tokenizer": {
"type": "pattern",
"pattern": "[ \\[\\](){}]" // 按空格和括号分词
}
},
"analyzer": {
"log_analyzer": {
"tokenizer": "log_tokenizer",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"properties": {
"message": {
"type": "text",
"analyzer": "log_analyzer"
},
"level": {
"type": "keyword"
},
"timestamp": {
"type": "date"
}
}
}
}
案例 3:搜索引擎(知乎、CSDN)
json
PUT /articles
{
"settings": {
"analysis": {
"analyzer": {
"article_analyzer": {
"tokenizer": "ik_max_word",
"filter": ["lowercase"],
"char_filter": ["html_strip"] // 去除 HTML
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart",
"boost": 3 // 标题权重更高
},
"content": {
"type": "text",
"analyzer": "article_analyzer",
"search_analyzer": "ik_smart"
},
"tags": {
"type": "keyword"
}
}
}
}
七、最佳实践
7.1 分词器选择原则
原则 1:索引时和搜索时分词策略不同
索引时:使用细粒度分词(ik_max_word)
→ 建立更多索引词,提高召回率
搜索时:使用粗粒度分词(ik_smart)
→ 减少噪音,提高精确度
原则 2:根据数据类型选择
结构化数据(状态、ID)→ keyword
英文文本 → standard / english
中文文本 → ik / jieba
日志数据 → whitespace / pattern
需要精确匹配 → keyword
需要模糊匹配 → n-gram
7.2 性能优化建议
(1)避免过度分词
json
// ❌ 不推荐:过细的 n-gram
{
"tokenizer": {
"type": "ngram",
"min_gram": 1,
"max_gram": 20 // 会产生海量词元
}
}
// ✅ 推荐:合理的 edge_ngram
{
"tokenizer": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 10
}
}
(2)合理使用停用词
json
{
"filter": {
"my_stop": {
"type": "stop",
"stopwords": ["的", "了", "在", "是", "我"] // 自定义停用词
}
}
}
(3)控制同义词数量
// ❌ 过多同义词影响性能
手机, 电话, 移动电话, 智能机, 大哥大, ...
// ✅ 核心同义词
手机, 电话
7.3 测试分词效果
方法 1:_analyze API
json
POST /my_index/_analyze
{
"analyzer": "ik_smart",
"text": "Elasticsearch 分词器原理"
}
方法 2:_validate API
json
GET /my_index/_validate/query?explain
{
"query": {
"match": {
"title": "分词器"
}
}
}
// 查看实际执行的查询
方法 3:_termvectors API
json
GET /my_index/_termvectors/1?fields=title
// 查看文档的实际分词结果
7.4 常见问题与解决方案
问题 1:搜不到结果
原因:索引时和搜索时分词器不一致
解决方案:
PUT /my_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart" // 明确指定搜索分词器
}
}
}
}
问题 2:中文单字分词
原因:未安装中文分词器
解决方案:安装 IK、jieba 等分词插件
问题 3:同义词不生效
原因:同义词文件路径错误或格式问题
检查:
1. 文件路径:config/analysis/synonym.txt
2. 文件编码:UTF-8
3. 格式:每行一组同义词,逗号分隔
4. 重启 Elasticsearch
问题 4:自定义词典不生效
IK 分词器解决方案:
1. 修改 config/analysis-ik/custom.dic
2. 更新 IKAnalyzer.cfg.xml
3. 重启 Elasticsearch
4. 或使用热更新(支持远程词典)
7.5 分词器调试技巧
技巧 1:逐步测试
json
// Step 1: 测试 tokenizer
POST /_analyze
{
"tokenizer": "ik_smart",
"text": "测试文本"
}
// Step 2: 添加 filter
POST /_analyze
{
"tokenizer": "ik_smart",
"filter": ["lowercase"],
"text": "测试文本"
}
// Step 3: 完整 analyzer
POST /_analyze
{
"analyzer": "my_analyzer",
"text": "测试文本"
}
技巧 2:对比不同分词器
json
POST /_analyze
{
"explain": true, // 详细信息
"analyzer": "ik_max_word",
"text": "中华人民共和国"
}
技巧 3:查看实际索引词
json
GET /my_index/_search
{
"query": {"match_all": {}},
"highlight": {
"fields": {"title": {}}
}
}
// 通过高亮查看实际匹配的词