Elasticsearch分析器
无论是内置的分析器(analyzer),还是自定义的分析器(analyzer),都是由字符过滤器(character filters)、分词器(tokenizers) 和 token过滤器( token filters)组成。char_filter是字符过滤器,filter是token filter。
字符过滤器(character filters)
字符过滤器以字符流的形式接受原始文本,并可以通过增加、删除和更改字符来转换字符流。分词之前预处理。
一个analyzer可以有0个或者多个character filters。
-
HTML字符过滤器(HTML Strip Character Filter): html_strip表示提出html标签;escaped_tags表示保留html标签。
# my_char_filter:自定义char_filter,剔除除标签外的所有的html标签 # tokenizer:keyword keyword分词器:整个输入作为一个单独词汇单元,方便特殊类型的文本进行索引和检索。针对邮政编码,地址等文本信息使用关键词分词器进行索引项建立非常方便 # my_analyzer:自定义分析器 DELETE my_index PUT my_index { "settings": { "analysis": { "char_filter": { "my_char_filter":{ "type":"html_strip", "escaped_tags": ["a"] } } , "analyzer": { "my_analyzer":{ "tokenizer":"keyword", "char_filter":"my_char_filter" } } } } } POST my_index/_analyze { "analyzer": "my_analyzer", "text": "
I'm so happy!
" } { "tokens" : [ { // 过滤之后的结果 "token" : """ I'm so happy! """, "start_offset" : 0, "end_offset" : 32, "type" : "word", "position" : 0 } ] } -
映射字符过滤器(Mapping Character Filter): type -> mapping 字符映射
# my_char_filter:自定义char_filter,利用type=mapping进行字符替换 # tokenizer:keyword keyword分词器:整个输入作为一个单独词汇单元,方便特殊类型的文本进行索引和检索。针对邮政编码,地址等文本信息使用关键词分词器进行索引项建立非常方便 # my_analyzer:自定义分析器 DELETE my_index PUT my_index { "char_filter": { "my_char_filter": { "type": "mapping", "mappings": [ "٠ => 0", "١ => 1", "٢ => 2", "٣ => 3", "٤ => 4", "٥ => 5", "٦ => 6", "٧ => 7", "٨ => 8", "٩ => 9" ] } }, "settings": { "analysis": { "analyzer": { "my_analyzer": { "tokenizer": "keyword", "char_filter": [ "my_char_filter" ] } } } } } POST my_index/_analyze { "analyzer": "my_analyzer", "text": "My license plate is ٢٥٠١٥" } { "tokens" : [ { "token" : "My license plate is 25015", "start_offset" : 0, "end_offset" : 25, "type" : "word", "position" : 0 } ] }
-
模式替换过滤器(Patten Replace Character Filter): type -> patten_replace 正则匹配
DELETE my_index # my_analyzer:自定义模式匹配分析器,正则匹配上的字符串将不再分词 PUT my_index { "settings": { "analysis": { "analyzer": { "my_analyzer": { "tokenizer": "standard", "char_filter": ["my_char_filter"] } }, "char_filter": { "my_char_filter": { "type": "pattern_replace", "pattern": "(\\d+)-(?=\\d)", "replacement": "$1_" } } } } } POST my_index/_analyze { "analyzer": "my_analyzer", "text": "My credit card is 123-456-789" } { "tokens" : [ { "token" : "My", "start_offset" : 0, "end_offset" : 2, "type" : "
", "position" : 0 }, { "token" : "credit", "start_offset" : 3, "end_offset" : 9, "type" : " ", "position" : 1 }, { "token" : "card", "start_offset" : 10, "end_offset" : 14, "type" : " ", "position" : 2 }, { "token" : "is", "start_offset" : 15, "end_offset" : 17, "type" : " ", "position" : 3 }, { "token" : "123_456_789", "start_offset" : 18, "end_offset" : 29, "type" : " ", "position" : 4 } ] }
分词器(Tokenizer)
一个分词器接受一个字符流,并将其拆分成单个token(通常是单个单词),并输出一个token流。
Tokenizer负责将文本拆分成单个token(一个一个的单词,这些单词叫token),就是一段文本被分隔成好几部分,相当于java的split。
分词器负责记录每个term的书序或位置,以及term所表示的原单词的开始和结束字符偏移量(文本被分词后的输出是一个term数组)。
一个分析器必须只能一个分词器
ES内置分词器 7.6 15种 自带分词器
① standard analyzer:默认分词器,中文支持的不理想,会逐字拆分。
1) max_token_length:最大令牌长度。如果看到令牌超过此长度,则将其max_token_length间隔分割。默认为255。
② Pattern Tokenizer:以正则匹配分隔符,把文本拆分成若干词项。
③ Simple Pattern Tokenizer:以正则匹配词项,速度比Pattern Tokenizer快。
④ whitespace analyzer:以空白符分隔 Tim_cookie-
代码样例:
#设置type为custom告诉Elasticsearch我们正在定义一个定制分析器。将此与配置内置分析器的方式进行比较: type将设置为内置分析器的名称,如 standard或simple # 自定义字符过滤器 test_char_filter ,将 & 替换为 and | 替换为 or # 自定义token filter, 停用词 is、in、at、the、a、for # 分词器增加标点过滤:模式匹配,去除 .,!? 四种标点符号 # 自定义分析器 my_analyzer 汇总以上三种自定义,同时character filter增加提出html,token filter 增加 字母小写。 PUT /test_analysis { "settings": { "analysis": { "char_filter": { "test_char_filter": { "type": "mapping", "mappings": [ "& => and", "| => or" ] } }, "filter": { "test_stopwords": { "type": "stop", "stopwords": ["is","in","at","the","a","for"] } }, "tokenizer": { "punctuation": { "type": "pattern", "pattern": "[ .,!?]" } }, "analyzer": { "my_analyzer": { "type": "custom", "char_filter": [ "html_strip", "test_char_filter" ], "tokenizer": "standard", "filter": ["lowercase","test_stopwords"] } } } } } GET /test_analysis/_analyze { "text": "Teacher ma & zhang also thinks [mother's friends] is good | nice!!!", "analyzer": "my_analyzer" } # 执行结果 { "tokens" : [ { "token" : "teacher", "start_offset" : 0, "end_offset" : 7, "type" : "
", "position" : 0 }, { "token" : "ma", "start_offset" : 8, "end_offset" : 10, "type" : " ", "position" : 1 }, { "token" : "and", "start_offset" : 11, "end_offset" : 12, "type" : " ", "position" : 2 }, { "token" : "zhang", "start_offset" : 13, "end_offset" : 18, "type" : " ", "position" : 3 }, { "token" : "also", "start_offset" : 19, "end_offset" : 23, "type" : " ", "position" : 4 }, { "token" : "thinks", "start_offset" : 24, "end_offset" : 30, "type" : " ", "position" : 5 }, { "token" : "mother's", "start_offset" : 32, "end_offset" : 40, "type" : " ", "position" : 6 }, { "token" : "friends", "start_offset" : 41, "end_offset" : 48, "type" : " ", "position" : 7 }, { "token" : "good", "start_offset" : 53, "end_offset" : 57, "type" : " ", "position" : 9 }, { "token" : "or", "start_offset" : 58, "end_offset" : 59, "type" : " ", "position" : 10 }, { "token" : "nice", "start_offset" : 60, "end_offset" : 64, "type" : " ", "position" : 11 } ] }
Token过滤器(token filters)
token filters接受token流,并且可能会增加、删除或者更改token流;
不允许token过滤器更改每个token的位置和字符偏移。
一个分词器可能有0个或者多个token过滤器,它们按照顺序应用。
一般负责时态转换、大小写转换、同义词转换、语气词处理等。比如 has=>have him=>he apples=>apple the/oh/a=>干掉
-
代码样例-1:
DELETE my_index # setting 设置索引配置 # my_token_filter:自定义token过滤器,1~20个字符词条才会被搜索 # my_analyzer:自定义分析器;使用的token过滤器有:lowercase(系统) 和 my_token_filter(自定义) # type:custom 固定写法,表示自定义分析器 # tokenizer:standard 系统自带的分词器。 # mappings中定义字段映射,使用自定义的分析器。 # analyzer 指的是在建索引时的分词策略 # search_analyzer 指的是在查询时的分词策略 PUT my_index { "settings": { "analysis": { "filter": { "my_token_filter":{ "type":"edge_ngram", "min_gram":1, "max_gram":20 } } , "analyzer": { "my_analyzer":{ "type":"custom", "tokenizer":"standard", "filter":[ "lowercase", "my_token_filter" ] } } } } , "mappings": { "properties": { "keyword":{ "type": "text" , "analyzer": "my_analyzer" , "search_analyzer": "standard" } } } }
-
代码样例-2:
# 利用stardard 将文本分词之后的所有token进行小写。 GET _analyze { "tokenizer" : "standard", "filter" : ["lowercase"], "text" : "THE Quick FoX JUMPs" } # 自定义条件token过滤器 GET /_analyze { "tokenizer":"standard", "filter": [ { "type": "condition", "filter": [ "lowercase" ], "script": { "source": "token.getTerm().length() < 5" } } ], "text": "THE QUICK BROWN FOX" }
-
代码样例-3:
# 自定义分析器,采用英语内置的stopword(停用词) PUT /my_index { "settings": { "analysis": { "analyzer": { "my_analyzer":{ "type":"standard", "stopwords":"_english_" } } } } } GET my_index/_analyze { "analyzer": "my_analyzer", "text": "Teacher Ma is in the restroom" }
停用词:
停用词过滤:是文本分析中一个预处理方法。它的功能是过滤分词结果中的噪声(例如:的、是、啊等)
停用词:指在信息检索中,为节省存储空间和提高搜索效率,在处理自然语言数据(或文本)之前或之后会自动过滤掉某些字或词,这些字或词即被称为Stop Words(停用词)。这些停用词都是人工输入、非自动化生成的,生成后的停用词会形成一个停用词表。但是,并没有一个明确的停用词表能够适用于所有的工具。甚至有一些工具是明确地避免使用停用词来支持短语搜索的。
移除停用词的工作是由stop停用词过滤器完成的,可以通过创建自定义分析器来使用它。但是也有一些自带的分析器预制使用停用词过滤器
-
语言分析器:每个语言分析器默认使用 该语言相适应的停用词列表。特定语言的默认停用词,可以通过使用
_lang_
符号来指定。如 english 英语分析器使用 :_english_ 停用词列表。"stopwords": "_english_";# 默认的停用词是 _english_ # 本例通过 _none_ 禁用了停用词 PUT /my_index { "settings": { "analysis": { "analyzer": { "my_english": { "type": "english", "stopwords": "_none_" } } } } } # 停用词 可以指定路径 # 停用词文件的路径,该路径相对于 Elasticsearch 的 config 目录 PUT /my_index { "settings": { "analysis": { "analyzer": { "my_english": { "type": "english", "stopwords_path": "stopwords/english.txt" } } } } }
-
standard 标准分析器:默认使用空的停用词列表:_none_,实际是禁用了停用词。
# 自定义分析器 my_analyzer # 标准的standard分析器,进行了一些自定义配置 # 过滤掉停用词 and 和 the PUT /my_index { "settings": { "analysis": { "analyzer": { "my_analyzer": { "type": "standard", "stopwords": [ "and", "the" ] } } } } }
- pattern模式分析器:与standard分析器类似,默认使用空的的停用词里诶博爱:为_none_。
分词器(analyzer)处理过程
搜索引擎的人性化(Normalization)
为key_words提供更加完整的倒排索引。
如:时态转化(like | liked),单复数转化(man | men),全写简写(china | cn),同义词(small | little)等。
如:china 搜索时,如果条件为cn是否可搜索到。
如:dogs,搜索时,条件为dog是否可搜索到数据。
如果可以使用简写(cn)或者单复数(dog&dogs)搜索到想要的结果,那么称为搜索引擎normalization人性化。
normalization是为了提升召回率的(recall),就是提升搜索能力的。
normalization是配合分词器(analyzer)完成其功能的。
分词器的功能就是处理Document中的field的。就是创建倒排索引过程中用于切分field数据的。
如:I think dogs is human’s best friend.在创建倒排索引的时候,使用分词器实现数据的切分。
上述的语句切分成若干的词条,分别是: think dog human best friend。
常见搜索条件有:think、 human、 best、 friend,很少使用is、a、the、i这些数据作为搜索条件。