ES之分析器(Analyzer)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES之分析器(Analyzer)相关的知识,希望对你有一定的参考价值。
参考技术A 把输入的文本块按照一定的策略进行分解,并建立倒排索引。在Lucene的架构中,这个过程由分析器(analyzer)完成。文本分词会发生在两个地方:
默认ES使用 standard analyzer ,如果默认的分词器无法符合你的要求,可以自己配置。
可以通过 _analyzer API来测试分词的效果。
响应结果如下:
同时你也可以按照下面的规则组合使用:
响应结果如下:
与之前不同的是,它会将切分的词进行小写处理。这是因为我添加了一个 lowercase 的 token filter ,它会将分词的词进行小写处理。
我们还可以在创建索引前设置一个自定义的分词器:
上面操作我们自定义了一个分词器 std_folded ,它的 tokenizer 为 standard ,同时有两个 token filter 分别为: lowercase 和 asiciifolding 。我们在定义mapping时,设置了一个字段名为 my_text ,它的类型为 text ,我们指定它使用的分词器为我们定义的 std_folded .在分词测试中,我们获取的结果为:
内置的分词器无需任何配置我们就可以使用。但是我们可以修改内置的部分选项修改它的行为。
上面的例子中,我们配置分词器 std_english ,它使用的分词器为 standard 分词器,他的停词列表设置为 _english_ .然后字段 my_text 使用的是 standard 分词器,而字段 my_text.english 使用的是我们配置的 std_english .最后的分词测试结果如下:
结果1和2的区别为,结果2中的停词 The 被删除,而结果1中的并没有。这是因为 my_text.english 配置了停词。
当内置的分词器无法满足需求时,可以创建 custom 类型的分词器。
上面的示例中定义了一个名为 my_custom_analyzer 的分词器,该分词器的 type 为 custom , tokenizer 为 standard , char_filter 为 hmtl_strip , filter 定义了两个分别为: lowercase 和 asciifolding 。运行分词测试:
结果如下:
分词器的使用地方有两个:
如果设置手动设置了分词器,ES将按照下面顺序来确定使用哪个分词器:
在搜索时,通过下面参数依次检查搜索时使用的分词器:
如果上面几种都未设置,则使用默认的 standard 分词器。
上面指定创建索引时使用的默认分词器为 simple 分词器,而搜索的默认分词器为 whitespace 分词器。
ES系列六ES字段类型及ES内置analyzer分析
一、背景知识
在Es中,字段的类型很关键:
在索引的时候,如果字段第一次出现,会自动识别某个类型,这种规则之前已经讲过了。
那么如果一个字段已经存在了,并且设置为某个类型。再来一条数据,字段的数据不与当前的类型相符,就会出现字段冲突的问题。如果发生了冲突,在2.x版本会自动拒绝。
如果自动映射无法满足需求,就需要使用者自己来设置映射类型,因此,就需要使用者了解ES中的类型。
下面就步入正题吧!
二、字段中的索引和存储
其中需要说明的是:
1、index定义字段的分析类型以及检索方式
如果是no,则无法通过检索查询到该字段;
如果设置为not_analyzed则会将整个字段存储为关键词,常用于汉字短语、邮箱等复杂的字符串;
如果设置为analyzed则将会通过默认的standard分析器进行分析
2、store定义了字段是否存储
在《ES IN ACTION》中有这样一段描述:
This might be useful when you ask Elasticsearch for a particular field because retrieving a single stored field will be faster than retrieving the entire _source and extracting that field from it, especially when you have large documents.NOTE When you store individual fields as well, you should take into account that the more you store, the bigger your index gets. Usually bigger indices imply slower indexing and slower searching.
意思是,在ES中原始的文本会存储在_source里面(除非你关闭了它)。默认情况下其他提取出来的字段都不是独立存储的,是从_source里面提取出来的。当然你也可以独立的存储某个字段,只要设置store:true即可。
独立存储某个字段,在频繁使用某个特殊字段时很常用。而且获取独立存储的字段要比从_source中解析快得多,而且额外你还需要从_source中解析出来这个字段,尤其是_source特别大的时候。
不过需要注意的是,独立存储的字段越多,那么索引就越大;索引越大,索引和检索的过程就会越慢....
3、Text vs. keyword
ElasticSearch 5.0以后,string类型有重大变更,移除了string类型,string字段被拆分成两种新的数据类型: text用于全文搜索的,而keyword用于关键词搜索。
ElasticSearch对字符串拥有两种完全不同的搜索方式. 你可以按照整个文本进行匹配, 即关键词搜索(keyword search), 也可以按单个字符匹配, 即全文搜索(full-text search). 对ElasticSearch稍有了解的人都知道, 前者的字符串被称为not-analyzed字符, 而后者被称作analyzed字符串。
Text:会分词,然后进行索引
支持模糊、精确查询
不支持聚合
keyword:不进行分词,直接索引
支持模糊、精确查询
支持聚合
text用于全文搜索的, 而keyword用于关键词搜索.
如果想做类似于sql中的like查询,可定义为keyword并使用通配符wildcard方式查询。
ElasticSearch字符串将默认被同时映射成text和keyword类型,将会自动创建下面的动态映射(dynamic mappings):
{
"foo": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
基于这个映射你即可以在foo字段上进行全文搜索, 也可以通过foo.keyword字段实现关键词搜索及数据聚合。
禁用这个特性也很方便: 你只需要在定义mapping时显式声明字符串字段的类型或者使用一个动态模板(dynamic template)来匹配你所有的字符串字段即可. 例如通过下面的dynamic template就可以恢复到在ElasticSearch 2.x中使用的dynamic template的效果:
{
"match_mapping_type": "string",
"mapping": {
"type": "text"
}
}
4、Numeric
数值类型,注意numeric并不是一个类型,它包括多种类型,比如:long,integer,short,byte,double,float,每种的存储空间都是不一样的,一般默认推荐integer和float。
重要的参数:
index分析
not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
no
store存储
true 独立存储
false(默认)不存储,从_source中解析
5、date
日期类型,该类型可以接受一些常见的日期表达方式。
重要的参数:
index分析
not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
no
store存储
true 独立存储
false(默认)不存储,从_source中解析
format格式化
strict_date_optional_time||epoch_millis(默认)
你也可以自定义格式化内容,比如
"date": {
"type": "date",
"format": "yyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
6、IP
常用参数:
index分析
not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
no
store存储
true 独立存储
false(默认)不存储,从_source中解析
7、boolean
布尔类型,所有的类型都可以标识布尔类型。
False: 表示该值的有:false, "false", "off", "no", "0", "" (empty string), 0, 0.0
True: 所有非False的都是true
重要的参数:
index分析
not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
no
store存储
true 独立存储
false(默认)不存储,从_source中解析
三、内置分词器
1、基本概念
全文搜索引擎会用某种算法对要建索引的文档进行分析, 从文档中提取出若干Token(词元), 这些算法称为Tokenizer(分词器), 这些Token会被进一步处理, 比如转成小写等, 这些处理算法被称为Token Filter(词元处理器), 被处理后的结果被称为Term(词), 文档中包含了几个这样的Term被称为Frequency(词频)。引擎会建立Term和原文档的Inverted Index(倒排索引), 这样就能根据Term很快到找到源文档了。文本被Tokenizer处理前可能要做一些预处理, 比如去掉里面的HTML标记, 这些处理的算法被称为Character Filter(字符过滤器), 这整个的分析算法被称为Analyzer(分析器)。
ES内置了很多Analyzer, 还有很多第三方的Analyzer插件, 比如一些处理中文的Analyzer(中文分词)。
analyzer、 tokenizer、 filter可以在elasticsearch.yml 配置, 下面是配置例子
index :
analysis :
analyzer :
standard :
type : standard
stopwords : [stop1, stop2]
myAnalyzer1 :
type : standard
stopwords : [stop1, stop2, stop3]
max_token_length : 500
# configure a custom analyzer which is
# exactly like the default standard analyzer
myAnalyzer2 :
tokenizer : standard
filter : [standard, lowercase, stop]
tokenizer :
myTokenizer1 :
type : standard
max_token_length : 900
myTokenizer2 :
type : keyword
buffer_size : 512
filter :
myTokenFilter1 :
type : stop
stopwords : [stop1, stop2, stop3, stop4]
myTokenFilter2 :
type : length
min : 0
max : 2000
2、组装自己的analyzer
ES内置若干analyzer, 另外还可以用内置的character filter, tokenizer, token filter组装一个analyzer(custom analyzer), 比如
index :
analysis :
analyzer :
myAnalyzer :
tokenizer : standard
filter : [standard, lowercase, stop]
3、使用第三方分词器
如果你要使用第三方的analyzer插件,需要先在配置文件elasticsearch.yml中注册, 下面是配置IkAnalyzer的例子
index:
analysis:
analyzer:
ik:
alias: [ik_analyzer]
type: org.elasticsearch.index.analysis.IkAnalyzerProvider
当一个analyzer在配置文件中被注册到一个名字(logical name)下后,在mapping定义或者一些API里就可以用这个名字来引用该analyzer了,比如
"message": {
"type": "string",
"indexAnalyzer": "ik",
"searchAnalyzer": "ik"
}
4、配置默认分词器
如果没有指定索引和搜索用的analyzer,ES会用默认的analyzer来处理,也就是名字(logical name)为default, default_index, default_search的analyzer。从名字可以看出来,default是索引和搜索时用的默认的analyzer,default_index是索引时用的默认的analyzer, default_search是查询时用的默认analyzer。
下面是在elasticsearch.yml中配置默认analyzer的例子
index:
analysis:
analyzer:
default_index:
tokenizer: standard
filter: [standard, lowercase, my_synonym, my_snow]
default_search:
tokenizer: standard
filter: [standard, lowercase, stop]
或者用这种格式
index.analysis.analyzer.default.type : "mmseg"
一个analyzer可以起若干别名,比如在下面的例子中,standard analyzer可以用alias1或者alias2来引用
index :
analysis :
:
standard :
alias: [alias1, alias2]
type : standard
stopwords : [test1, test2, test3]
下面是内置的一些analyzer:
analyzer | logical name | description |
standard analyzer | standard | standard tokenizer, standard filter, lower case filter, stop filter |
simple analyzer | simple | lower case tokenizer |
stop analyzer | stop | lower case tokenizer, stop filter |
keyword analyzer | keyword | 不分词,内容整体作为一个token(not_analyzed) |
pattern analyzer | whitespace | 正则表达式分词,默认匹配\W+ |
language analyzers | lang | 各种语言 |
snowball analyzer | snowball | standard tokenizer, standard filter, lower case filter, stop filter, snowball filter |
custom analyzer | custom | 一个Tokenizer, 零个或多个Token Filter, 零个或多个Char Filter |
5.tokenizer
ES内置的tokenizer列表。
tokenizer | logical name | description |
standard tokenizer | standard | |
edge ngram tokenizer | edgeNGram | |
keyword tokenizer | keyword | 不分词 |
letter analyzer | letter | 按单词分 |
lowercase analyzer | lowercase | letter tokenizer, lower case filter |
ngram analyzers | nGram | |
whitespace analyzer | whitespace | 以空格为分隔符拆分 |
pattern analyzer | pattern | 定义分隔符的正则表达式 |
uax email url analyzer | uax_url_email | 不拆分url和email |
path hierarchy analyzer | path_hierarchy | 处理类似/path/to/somthing样式的字符串 |
6、token filter
ES内置的token filter列表。
token filter | logical name | description |
standard filter | standard | |
ascii folding filter | asciifolding | |
length filter | length | 去掉太长或者太短的 |
lowercase filter | lowercase | 转成小写 |
ngram filter | nGram | |
edge ngram filter | edgeNGram | |
porter stem filter | porterStem | 波特词干算法 |
shingle filter | shingle | 定义分隔符的正则表达式 |
stop filter | stop | 移除 stop words |
word delimiter filter | word_delimiter | 将一个单词再拆成子分词 |
stemmer token filter | stemmer | |
stemmer override filter | stemmer_override | |
keyword marker filter | keyword_marker | |
keyword repeat filter | keyword_repeat | |
kstem filter | kstem | |
snowball filter | snowball | |
phonetic filter | phonetic | https://github.com/elastic/elasticsearch-analysis-phonetic |
synonym filter | synonyms | 处理同义词 |
compound word filter | dictionary_decompounder, hyphenation_decompounder |
分解复合词 |
reverse filter | reverse | 反转字符串 |
elision filter | elision | 去掉缩略语 |
truncate filter | truncate | 截断字符串 |
unique filter | unique | |
pattern capture filter | pattern_capture | |
pattern replace filte | pattern_replace | 用正则表达式替换 |
trim filter | trim | 去掉空格 |
limit token count filter | limit | 限制token数量 |
hunspell filter | hunspell | 拼写检查 |
common grams filter | common_grams | |
normalization filter | arabic_normalization, persian_normalization |
7、character filter
ES内置的character filter列表
character filter | logical name | description |
mapping char filter | mapping | 根据配置的映射关系替换字符 |
html strip char filter | html_strip | 去掉HTML元素 |
pattern replace char filter | pattern_replace | 用正则表达式处理字符串 |
以上是关于ES之分析器(Analyzer)的主要内容,如果未能解决你的问题,请参考以下文章
ES analyzer和search_analyzer的比较
第三篇:Spark SQL Catalyst源码分析之Analyzer