讲一下elastic search 的分词原理
文章目录
- 一、分词的核心作用
- 二、分词器(Analyzer):分词的“执行单元”
- 1. 字符过滤器(Character Filter):预处理原始文本
- 2. 分词器(Tokenizer):拆分文本为词元(Token)
- 3. 词元过滤器(Token Filter):优化词元
- 三、内置分词器与自定义分词器
- 四、中文分词的特殊性
- 五、关键注意事项
- 总结
Elasticsearch(ES)的分词是全文检索的核心环节,其本质是将 原始文本(如一句话、一段日志)拆分成若干个有意义的“词(Term)”,这些词会被存入倒排索引,供后续查询时快速匹配。分词的质量直接影响检索的准确性(能否精准匹配)和召回率(能否找到所有相关结果)。
一、分词的核心作用
在ES中,分词发生在两个阶段:
- 索引时:当文档写入ES时,会对
text
类型的字段进行分词,将拆分后的Term存入倒排索引(记录Term与文档的对应关系)。 - 搜索时:用户输入查询文本时,ES会对查询文本执行相同的分词逻辑,得到Term后,去倒排索引中匹配包含这些Term的文档。
关键原则:索引和搜索时的分词逻辑必须一致(或兼容),否则会导致“索引的Term”与“搜索的Term”不匹配,查询不到结果。例如:索引时将“Hello”拆分为小写“hello”,但搜索时未小写处理,就会匹配失败。
二、分词器(Analyzer):分词的“执行单元”
ES的分词由分词器(Analyzer) 完成,一个分词器是三个组件的组合,按顺序执行:
原始文本 → 字符过滤器(Character Filter) → 分词器(Tokenizer) → 词元过滤器(Token Filter) → 最终Term
1. 字符过滤器(Character Filter):预处理原始文本
作用:在文本被拆分前,对原始字符串进行清洗或转换(如去除无用字符、替换特殊符号)。
- 可配置多个,按顺序执行。
- 常见类型:
html_strip
:去除HTML标签(如将<p>hello</p>
转换为hello
)。mapping
:替换指定字符(如将:-)
替换为happy
)。pattern_replace
:用正则表达式替换(如将数字替换为NUMBER
)。
2. 分词器(Tokenizer):拆分文本为词元(Token)
作用:将预处理后的文本按规则拆分成若干个“词元(Token)”(尚未最终存入索引的临时词),是分词的核心步骤。
- 一个分词器必须且只能有一个Tokenizer。
- 拆分规则由Tokenizer的类型决定,例如:
- Standard Tokenizer(默认):按Unicode文本分割规则拆分(空格、标点、符号等视为分隔符),并去除大部分标点。
例:"Hello, world! 123"
→ 拆分为["Hello", "world", "123"]
。 - Whitespace Tokenizer:仅按空格拆分,保留标点。
例:"Hello, world! 123"
→ 拆分为["Hello,", "world!", "123"]
。 - Letter Tokenizer:仅按非字母字符拆分(只保留字母组成的词)。
例:"Hello, world! 123"
→ 拆分为["Hello", "world"]
(数字和标点被当作分隔符)。 - 中文分词器(如IK Tokenizer):针对中文无空格的特点,按语义拆分(基于词典和规则)。
例:"我爱北京天安门"
→ 拆分为["我", "爱", "北京", "天安门"]
。
- Standard Tokenizer(默认):按Unicode文本分割规则拆分(空格、标点、符号等视为分隔符),并去除大部分标点。
3. 词元过滤器(Token Filter):优化词元
作用:对Tokenizer输出的词元进行二次处理(如过滤、转换、增删),最终生成存入索引的Term。
- 可配置多个,按顺序执行。
- 常见类型:
lowercase
:将词元转为小写(解决大小写不敏感问题)。
例:["Hello", "World"]
→ 转为["hello", "world"]
。stop
:去除停用词(无实际意义的词,如“的”“a”“the”)。
例:["我", "的", "北京"]
→ 过滤后["我", "北京"]
。synonym
:替换同义词(提升召回率)。
例:配置“西红柿→番茄”,则["西红柿"]
→ 转为["番茄", "西红柿"]
(同时保留原词和同义词)。stemmer
:词干提取(将动词变体转为原型,如“running”→“run”)。
三、内置分词器与自定义分词器
ES提供了多种内置分词器(已组合好Character Filter、Tokenizer、Token Filter),满足常见场景:
standard
(默认):Standard Tokenizer + lowercase + stop
(默认去除英文停用词)。simple
:Letter Tokenizer + lowercase
(只保留字母并小写)。whitespace
:仅Whitespace Tokenizer
(按空格拆分,不做其他处理)。keyword
:特殊分词器,不拆分文本(将整个文本作为一个Term,类似keyword
类型的字段)。
如果内置分词器不满足需求(如中文分词、自定义规则),可自定义分词器,例如:
// 定义一个中文分词器(使用IK分词+小写转换+过滤停用词)
"settings": { "analysis": { "analyzer": { "my_ik_analyzer": { // 自定义分词器名称 "type": "custom", "char_filter": [], // 无字符过滤 "tokenizer": "ik_max_word", // IK分词器(细粒度拆分) "filter": ["lowercase", "stop"] // 转小写+过滤停用词 } } }
}
四、中文分词的特殊性
英文等语言天然以空格分隔单词,分词规则简单;但中文无空格,且存在“一词多义”“歧义”(如“南京市长江大桥”可拆分为“南京市/长江大桥”或“南京/市长/江大桥”),因此需要专门的中文分词器:
- IK分词器:最常用的中文分词器,支持“ik_smart”(粗粒度拆分,适合精准匹配)和“ik_max_word”(细粒度拆分,适合召回率优先)。
- Jieba分词器:基于Python的分词库,ES可通过插件集成,支持自定义词典和新词发现。
- THULAC:清华大学开源的分词工具,精度较高,但性能略低。
中文分词的核心是词典+规则+模型:
- 词典:内置常用词库(如“北京”“天安门”),确保已知词正确拆分。
- 规则:处理未登录词(词典中没有的词,如网络新词“内卷”)。
- 模型:部分分词器结合机器学习模型(如BERT),解决歧义问题(如通过上下文判断拆分方式)。
五、关键注意事项
-
字段类型与分词:
text
类型:会被分词,用于全文检索。keyword
类型:不分词(整个字段作为一个Term),用于精确匹配、排序、聚合。
(建议对text
字段同时设置keyword
子字段,如name.keyword
,兼顾检索和聚合)。
-
索引与搜索分词器一致性:
- 索引时用
analyzer
(默认与字段配置一致),搜索时用search_analyzer
(默认与analyzer
相同)。 - 若需特殊处理(如搜索时用更粗粒度的分词),可单独配置
search_analyzer
。
- 索引时用
-
分词效果测试:
可通过ES的_analyze
API测试分词结果,验证是否符合预期:GET /_analyze { "analyzer": "ik_max_word", "text": "我爱北京天安门" }
总结
ES的分词是“文本预处理→拆分→优化”的流水线过程,核心是通过分词器将文本转化为可检索的Term。合理配置分词器(尤其是中文场景)是提升检索效果的关键——既需要准确拆分有意义的词,又要通过过滤、同义词等处理平衡“精准度”和“召回率”。