ES内置的Analyzer分析器
es自带了许多内置的Analyzer分析器,无需配置就可以直接在index中使用:
- 标准分词器(standard):以单词边界切分字符串为terms,根据Unicode文本分割算法。它会移除大部分的标点符号,小写分词后的term,支持停用词。
- 简单分词器(simple):该分词器会在遇到非字母时切分字符串,小写所有的term。
- 空格分词器(whitespace):遇到空格字符时切分字符串,
- 停用词分词器(stop):类似简单分词器,同时支持移除停用词。
- 关键词分词器(keyword):无操作分词器,会输出与输入相同的内容作为一个single term。
- 模式分词器(pattern):使用正则表达式讲字符串且分为terms。支持小写字母和停用词。
- 语言分词器(language):支持许多基于特定语言的分词器,比如english或french。
- 签名分词器(fingerprint):是一个专家分词器,会产生一个签名,可以用于去重检测。
- 自定义分词器:如果内置分词器无法满足你的需求,可以自定义custom分词器,根据不同的character filters,tokenizer,token filters的组合 。例如IK就是自定义分词器。
- word_delimiter:将一个单词再拆成子分词
详见文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-analyzers.html
拼音分词器
1. 在线安装
1 | # 进入容器内部 |
要实现根据字母做补全,就必须对文档按照拼音分词。在GitHub上恰好有elasticsearch的拼音分词插件。地址:https://github.com/medcl/elasticsearch-analysis-pinyin

2. 离线安装
将zip下载到本地, 解压到plugins下的analysis-pinyin文件夹下
3. pinyin分词器的配置参数列表
| 参数 | 默认值 | 说明 | 注释 |
|---|---|---|---|
| keep_first_letter | true | 刘德华>ldh | 是否需要拼音首字母 |
| keep_separate_first_letter | false | 刘德华>l,d,h | 是否需要拼音首字母分开每个字母,为了不让搜索结果过于混乱、无关,这个选项就应该为默认值false |
| limit_first_letter_length | 16 | set max length of the first_letter result(设置 first_letter 结果的最大长度) | 限制一个长词的各字拼音首字母连起来的最大长度。比如,该值设置成3,有个词是"四大天王",则其拼音首字母为"sdt",取前三个拼音首字母。一般这个字段就为默认。 |
| keep_full_pinyin | true | 刘德华> [liu,de,hua] | |
| keep_joined_full_pinyin | false | 刘德华> [liudehua] | 这个参数要注意下,是否有必要主动设置成true |
| keep_none_chinese | true | keep non chinese letter or number in result(结果中保留非中文字母或数字) | 默认为true,不过一般会主动设置为false,因为在使用pinyin的场景中都是想搜索中文,非中文字符可以过掉 |
| keep_none_chinese_together | true | true:DJ音乐家 -> DJ,yin,yue,jia;false:DJ音乐家 -> D,J,yin,yue,jia | |
| keep_none_chinese_in_first_letter | true | 刘德华AT2016->ldhat2016 | 在实际使用过程中,该项最好不要默认,主动设置为false,因为本来该插件就是针对中文拼音使用的,大部分查询场景中都是针对中文拼音的搜索,如果将non chinese字符也涵盖进来,容易搜错。 另外,如果某个字段,既可能是中文又可能是英文,同时你默认keep_none_chinese_in_first_letter 为true,则英文会被分成这样: ![]() |
| keep_none_chinese_in_joined_full_pinyin | false | eg: 刘德华2016->liudehua2016 | 是否在joined_full_pinyin中保留非中文字符,看需求决定,如果不需要则需要主动设置为false |
| none_chinese_pinyin_tokenize | true | 如果是拼音,则将非中文字母分成单独的拼音词; eg: liudehuaalibaba13zhuanghan -> liu,de,hua,a,li,ba,ba,13,zhuang,han; 注: keep_none_chinese and keep_none_chinese_together 两项必须先启用 | 默认为true,这个最好主动设置为false。因为非中文字符一般是英文单词或数字,这些如果要被分词的话,会变成这样![]() 分词这么细粒度会导致搜索结果过于模糊。 |
| keep_original | false | 启用此选项时,也将保留原始输入 | 默认为false,看具体需求,再决定是否需要设置为true来保留原始text |
| lowercase | true | 非中文字母转小写 | |
| trim_whitespace | true | 剔除空格 | |
| remove_duplicated_term | false | 删除重复的术语; eg: de的 > de | |
| ignore_pinyin_offset | true | 在6.0之后,偏移被严格约束,不允许重叠标记,使用该参数,通过忽略偏移将允许重叠标记,请注意,所有与位置相关的查询或突出显示将变得不正确,您应该使用多个字段并为不同的查询目的指定不同的设置。如果需要偏移,请将其设置为false。默认值:true。 |
IK分词器
1.在线安装ik插件
1 | 进入容器内部 |
2.离线安装ik插件

将zip下载到本地, 解压到plugins下的ik文件夹下
4)重启容器
1 | 4、重启容器 |
1 | # 查看es日志 |
5)测试
IK分词器包含两种模式:
ik_smart:最少切分ik_max_word:最细切分
1 | GET /_analyze |
3 扩展词词典
随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中并不存在。比如:“奥力给”,“传智播客” 等。
所以我们的词汇也需要不断的更新,IK分词器提供了扩展词汇的功能。
1)打开IK分词器config目录:

2)在IKAnalyzer.cfg.xml配置文件内容添加:
1 |
|
3)新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改
1 | 传智播客 |
4)重启elasticsearch
1 | docker restart es |

日志中已经成功加载ext.dic配置文件
5)测试效果:
1 | GET /_analyze |
注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑
4 停用词词典
在互联网项目中,在网络间传输的速度很快,所以很多语言是不允许在网络上传递的,如:关于宗教、政治等敏感词语,那么我们在搜索时也应该忽略当前词汇。
IK分词器也提供了强大的停用词功能,让我们在索引时就直接忽略当前的停用词汇表中的内容。
1)IKAnalyzer.cfg.xml配置文件内容添加:
1 |
|
3)在 stopword.dic 添加停用词
1 | 习大大 |
4)重启elasticsearch
1 | # 重启服务 |
日志中已经成功加载stopword.dic配置文件
注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑
测试分词器安装是否成功
1 | GET /_cat/plugins?pretty |
ngram分词器
简介
什么是ngram 分词器?
ngram分词器是ES自带的具有前缀匹配搜索功能的一个文本分词器。它能根据文本的步长逐步对写入的文本内容进行约束切割
ngram和index-time搜索推荐原理
搜索的时候,不用再根据一个前缀,然后扫描整个倒排索引了,而是简单的拿前缀去倒排索引中匹配即可,如果匹配上了,那么就好了,就和match query全文检索一样。
1 | eg: quick 为列: |
ngram分词实践
1,定义一个索引,并指定分词器ngram;
1 | PUT db_content_testserver2 |
2, 创建type,并指定content 字段分词器为"ngram_analyzer"
1 | PUT db_content_testserver2/_mapping/t_article |
3, 写入测试数据
1 | POST db_content_testserver2/t_article |
4,我们可以测试一下上面的分词,是否能正常分词;
1 | POST db_content_testserver2/_analyze |
wildcard的替代方案: ngram+term/match_phrase
背景
1.ES模糊查询wildcard查询极耗机器CPU资源,查询耗时高,当并发量高时影响ES其它进程。
2.用户实际的模糊查询需求大多是左右模糊匹配。
match_phrase能够实现词组查询
比如brown fox会返回匹配…brown fox…的结果,此结果与wildcard查询传入brown fox的查询结果一致。相当于我们通过match_phrase实现wildcard查询效果,但此时只满足一些特许的模糊查询需求。
那如何对match_phrase的功能进行增强,让其能够满足所有条件?
从上面的查询示例可以看出,brown fox会返回匹配…brown fox…的结果,其根本原因在于索引时ES将…brown fox…分词成了brown,fox等单词。所以只要我们能够控制ES分词效果,将会最终满足我们的需求。而ES提供了丰富的分词功能。
ngram分词能够实现按指定长度对文本进行分词。
ngram可以指定min_gram,max_gram参数实现不同的分词效果。
例如:min_gram,max_gram配置为5时,quick.brown.fox分词后会产生quick,uick.,ick.b,ck.br,k.bro,.brow,brown,rown.,own.f,wn.fo,n.fox。
这时match_phrase会达到什么效果了?
a.用户输入quick,brown,k.bro等都能够返回quick.brown.fox。
b.用户输入brown.fox,brown.fox会被分词成brown,rown.,own.f等,此时同样会返回quick.brown.fox。
c.用户输入fox(长度小于ngram分词配置的分词长度时),不会返回任何结果。
如何正确返回查询条件长度小于5时的结果
利用ngram分词 + term查询可以实现所需查询效果。
ngram分词配置:min_gram配置为1,max_gram配置为4。例如quick将会被分词为q,u,i,… quic,uick。
term查询会对用户输入的条件进行精确匹配,比如输入uic,会返回quick。
方案
查询条件长度小于5时:使用ngram分词 + term查询
查询条件长度大于等于5时:使用ngram分词 + match_phrase查询
实施
创建索引
1 | PUT index_text_1 |
新增数据
1 | POST /index_text_1/_doc/_bulk |
查询语句
查询条件长度大于等于5时
1 | GET index_text_1/_search |
查询条件长度小于5时
1 | GET index_text_1/_search |
ngram使用思考
查询条件长度该设置成多少?
值太大,占用的存储资源就多(主要是short_char字段);值太小,long_char字段分词被分的太细,match_phrase查询耗时就会增加。
edge_gram分词器
这是一种倒金字塔的格式,预先把文本按这种方式给索引起来,然后按term查询即可(如果按IK分词,可能就分不出 “中华人民共” 这样一个词来)。
1 | 中华人民共和国 |
使用
1 | PUT xiaowu_test |
其他分词器
[1] 如何在elasticsearch中使用分词器: https://www.elastic.co/guide/en/elasticsearch/reference/current/configure-text-analysis.html
[2] 常用的中文分词器: https://github.com/medcl/elasticsearch-analysis-ik
[3] 拼音分词器: https://github.com/medcl/elasticsearch-analysis-pinyin
[4] elasticsearch官方文档中的一段介绍: https://www.elastic.co/guide/en/elasticsearch/reference/current/analyzer-anatomy.html#analyzer-anatomy
[5] 分析器: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-analyzers.html
[6] 自定义: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-custom-analyzer.html
[7] 字符过滤器: https://github.com/elastic/elasticsearch/edit/7.13/docs/reference/analysis/anatomy.asciidoc
[8] 字符过滤器: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-charfilters.html
[9] 分词器: https://github.com/elastic/elasticsearch/edit/7.13/docs/reference/analysis/anatomy.asciidoc
[10] whitespace: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-whitespace-tokenizer.html
[11] 分词器: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html
[12] token过滤器: https://github.com/elastic/elasticsearch/edit/7.13/docs/reference/analysis/anatomy.asciidoc
[13] lowercase: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html
[14] stop: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-stop-tokenfilter.html
[15] synonym: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-synonym-tokenfilter.html
[16] 词干提取token filters: https://www.elastic.co/guide/en/elasticsearch/reference/current/stemming.html
[17] token graphs: https://www.elastic.co/guide/en/elasticsearch/reference/current/token-graphs.html
[18] token过滤器: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenfilters.html
[19] 内置分析器示例: https://www.elastic.co/guide/en/elasticsearch/reference/current/configuring-analyzers.html
[20] standard分析器: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html
[21] character filters: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-charfilters.html
[22] tokenizer: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html
[23] token filters: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenfilters.html
[24] 配置: https://github.com/elastic/elasticsearch/edit/7.13/docs/reference/analysis/analyzers/custom-analyzer.asciidoc
[25] 内置分析器类型: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-analyzers.html
[26] tokenizer: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html
[27] character filters: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-charfilters.html
[28] token filters: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenfilters.html
[29] position_increment_gap: https://www.elastic.co/guide/en/elasticsearch/reference/current/position-increment-gap.html
[30] 示例配置: https://github.com/elastic/elasticsearch/edit/7.13/docs/reference/analysis/analyzers/custom-analyzer.asciidoc
[31] HTML 标记字符过滤器: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-htmlstrip-charfilter.html
[32] 标准分词器: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-tokenizer.html
[33] Lowercase Token Filter: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html
[34] ASCII-Folding Token Filter: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-asciifolding-tokenfilter.html
[35] Mapping Character Filter: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-mapping-charfilter.html
[36] Pattern Tokenizer: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-pattern-tokenizer.html
[37] Lowercase Token Filter: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html
[38] Stop Token Filter: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-stop-tokenfilter.html
[39] ngram Tokenizer: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-ngram-tokenizer.html