涉及知识点:
- ES 分词器工作原理
- ES 内置分词器
- IK 中文分词器
- 在Template Mapping中对不同field 配置分词器
相关背景介绍
Analysis
Analysis(文本分析): 将一段文本通过Analyzer划分为一系列term/token的过程称为Analysis,也叫分词。 简单说Analysis是通过Analyzer来实现的。
Index time analysis
当文档插入索引时,ES会对text类型的字段建立反向索引,反向索引通过Analyzer将文本拆分为tokens/terms,再将其指向包含对应数据的文档。
1 2 3 4 5 6
| # String被转为tokens, tokens又被转为小写并被简化为基础词根比如 (foxes → fox, jumped → jump, lazy → lazi) # 原句 The QUICK brown foxes jumped over the lazy dog! # Tokens [ quick, brown, fox, jump, over, lazi, dog ]
|
Search time analysis
Analysis同样也会应用到查询过程中,当我们使用full text queries(全文查询)时,比如match query。查询语句也会被分词,从而去匹配反向索引中的tokens/terms,并计算相关性得分。
指定查询时分词器: 优先使用查询语句配置的分词器,其次使用template filed中配置的分词器, 然后使用template index setting中配置的defautl,default_search分词器,最后是standard 分词器,最后是standard分词器。
An analyzer specified in the query itself.
The search_analyzer mapping parameter.
The analyzer mapping parameter.
An analyzer in the index settings called default_search.
An analyzer in the index settings called default.
The standard analyzer.
Analyzer的构成
Analyzer是由三个模块构成的: character filters, tokenizers, tokern filters。
用户可以使用内置的Analyzer,也可以自己自定义Analyzer。
character filters(字符过滤器): 在对文本进行分词之前,先进行预处理,比如说过滤html标签。
tokenizers(分词器): 将原有的语句切分为一系列的tokens/terms,并记录其起始位置和字符长度。 比如 whitespace分词器就会以空格来划分tokens
token filters(Token过滤器): 对切分后tokens进行处理,删除,添加或者修改token,如lowercase token filter就会小写化tokens,stop token filter就会删除无意义的助词(a, an, the, and等),synonym token filter则会添加同义词token。
执行顺序: Character filters(0或N个) –> Tokenizer(有且只有一个) –> Token filters(0或N个)
常见分词器及其使用
ES内置了许多分词器,这里简单常见的两种Standard Analyzer, Whitespace Anylyzer. 更多分词器和分词器细节配置,使用时再去了解即可,
Standard Analyzer(默认)
Standard是默认的分析器。它提供了基于语法的token划分(基于Unicode文本分割算法),适用于大部分语言(事实上中文日文就不行,别的语言没测)。

Whitespace Analyzer
Whitespace analyzer就是简单的将文本以空格进行划分。
如何自定义分词器
使用自定义分词器来满足一些客制化的需求。直接上例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| # 我们创建了一个自定义分词器取名为my_custom_analyzer # 自定义分词器的type需要设置为custom # tokenizer选择到了standard,当然也可以是任意内置或后续安装的其他tokenizer # character filter 和 filter选择了内置 PUT my_index { "settings": { "analysis": { "analyzer": { "my_custom_analyzer": { "type": "custom", "tokenizer": "standard", "char_filter": [ "html_strip" ], "filter": [ "lowercase", "asciifolding" ] } } } } }
POST my_index/_analyze { "analyzer": "my_custom_analyzer", "text": "Is this <b>déjà vu</b>?" }
# 这个例子中,我们的三个组件都使用了自定义的设置。 PUT my_index { "settings": { "analysis": { "analyzer": { "my_custom_analyzer": { "type": "custom", "char_filter": [ "emoticons" ], "tokenizer": "punctuation", "filter": [ "lowercase", "english_stop" ] } }, "tokenizer": { "punctuation": { "type": "pattern", "pattern": "[ .,!?]" } }, "char_filter": { "emoticons": { "type": "mapping", "mappings": [ ":) => _happy_", ":( => _sad_" ] } }, "filter": { "english_stop": { "type": "stop", "stopwords": "_english_" } } } } }
POST my_index/_analyze { "analyzer": "my_custom_analyzer", "text": "I'm a :) person, and you?" }
|
如何设置和测试分词器
如何在template中设置分词器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| # 在这里例子中,我们为title字段声明了`analyzer`(数据插入时使用),但并未context字段声明任何analyzer,而是在setting中配置了默认的analyzer,因此context字段将使用simple analyzer。若没有配置默认analyzer,text类型字段将默认使用standard analyzer. PUT my_index { "settings":{ "analysis":{ "analyzer":{ "default": { "type": "simple" } "my_analyzer":{ "type":"custom", "tokenizer":"standard", "filter":[ "lowercase" ] }, "my_stop_analyzer":{ "type":"custom", "tokenizer":"standard", "filter":[ "lowercase", "english_stop" ] } }, "filter":{ "english_stop":{ "type":"stop", "stopwords":"_english_" } } } }, "mappings":{ "_doc":{ "properties":{ "title": { "type":"text", "analyzer":"my_analyzer", "search_analyzer":"my_stop_analyzer", "search_quote_analyzer":"my_analyzer" } "context": { "type":"text" } } } } }
PUT my_index/_doc/1 { "title":"The Quick Brown Fox" }
PUT my_index/_doc/2 { "title":"A Quick Brown Fox" }
# 当前查询中"the quick brown fox"被引号框起,所以这个短语将会`search_quote_analyzer`所分析,如果没有引号,则会调用`search_analyzer`进行分析。 # 查询分析器的匹配顺序,见上文Analyzer。 GET my_index/_search { "query":{ "query_string":{ "query":"\"the quick brown fox\"" } } }
|
测试分词器
1 2 3 4 5 6 7
| GET _analyze { "tokenizer" : "keyword", "filter" : ["lowercase"], "char_filter" : ["html_strip"], "text" : "this is a <b>test</b>" }
|
IK分词器
在涉及到中文分词时,ES默认提供的分词器会将中文按照每个字来划分,不能正常使用。通常情况下我们会使用IK分词器,来对中文数据进行分词。
如何安装IK分词器
直接查看官方Readme
https://github.com/medcl/elasticsearch-analysis-ik
如何使用
IK支持两种颗粒度的拆分
ik_smart:会做最粗粒度的划分
ik_max_word: 做最细粒度的划分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| # 通过例子,直观了解
GET /_analyze { "text":"中华人民共和国国徽", "analyzer":"ik_smart" }
#TODO
GET /_analyze { "text":"中华人民共和国国徽", "analyzer":"ik_max_word" } #TODO
|