ElasticSearch08-分析器详解
1、分析器原理
- Elasticsearch的分词器(Analyzer)是全文搜索的核心组件,它负责将文本转换为一系列单词(term/token)的过程,也叫分词。
(1)分析器的构成
- 字符过滤器(Character Filters) :
- 接收原始文本字符流,可以通过添加、移除或改变字符来转变原始字符流。例如,可以将印度-阿拉伯数字转换为阿拉伯-拉丁数字,或从流中去除HTML元素等。
- 分词器(Tokenizer) :
- 接收字符流,将其分解为单独的tokens(通常是单个单词),并输出tokens流。例如,
whitespace
分词器在看到任何空格时将文本分解为tokens。它会将文本 "Quick brown fox!"
转换为多个terms [Quick, brown, fox!]
。分词器还负责记录每个term的顺序或位置以及该term所代表的原始单词的开始和结束字符偏移量。
- Token过滤器(Token Filters) :
- 接收令牌流,并且可以添加、删除或改变token。例如,
lowercase
token过滤器将所有token转换为小写,stop
token过滤器从token流中删除常用词(停用词),而synonym
token过滤器将同义词引入token流中。Token过滤器不允许更改每个token的位置或字符偏移量。
(2)分析器的工作流程
- 字符过滤器处理:文本首先通过字符过滤器,进行预处理,如去除HTML标签或格式转换。
- 分词器分词:经过预处理的文本进入分词器,分词器根据定义的规则(如空格、标点符号等)将文本拆分成单个词汇。
- Token过滤器处理:分词后的词汇通过一系列的Token过滤器,进行进一步的处理,如小写化、停用词过滤、同义词扩展等。
- 输出tokens:经过Token过滤器处理后的词汇成为最终的tokens,这些tokens将被用于构建倒排索引。
(3)分析器的重要性
- 分词器对于Elasticsearch的全文搜索至关重要,因为它直接影响到搜索的准确性和相关性。不同的语言和文本类型可能需要不同的分词器来最有效地处理文本。
- Elasticsearch提供了多种内置分词器,如
standard
、simple
、whitespace
、stop
等,以适应不同的应用场景。
- 用户也可以根据需要自定义分词器,以满足特定的分词需求。
2、常见内置分词器
分词器名称 |
描述 |
示例文本 |
分词结果示例 |
Standard Tokenizer |
使用Unicode文本分割算法,去除标点符号,适用于大多数欧洲语言 |
"Elasticsearch: Search & Analytics" |
["Elasticsearch", "Search", "Analytics"] |
Whitespace Tokenizer |
以空白字符为分词符,包括空格和制表符 |
"Elasticsearch, search & analytics" |
["Elasticsearch,", "search", "&", "analytics"] |
Lowercase Tokenizer |
类似Whitespace Tokenizer,但将所有tokens转换为小写 |
"Elasticsearch, search & analytics" |
["elasticsearch,", "search", "&", "analytics"] |
Keyword Tokenizer |
不进行分词,将整个文本作为一个单独的token |
"Elasticsearch: Search & Analytics" |
["Elasticsearch: Search & Analytics"] |
Pattern Tokenizer |
使用正则表达式进行分词,默认为\W+(非单词字符) |
"Elasticsearch: Search & Analytics" |
["Elasticsearch", "Search", "Analytics"] |
N-Gram Tokenizer |
创建n-grams,连续的字符序列 |
"elasticsearch"(2-gram) |
["el", "le", "ea", "ar", "rc", "ch", "ha", "an", "nt", "ts"] |
Edge N-Gram Tokenizer |
从单词的开始或结束部分生成n-grams |
"elasticsearch"(1-gram,edge) |
["e", "l", "s", "e", "l", "a", "r", "c", "h"] |
3、分词器使用场景
(1)索引阶段(Indexing Phase)
- **文档索引:**当文档被索引到Elasticsearch时,分词器用于将文本字段(如标题、内容等)转换为一系列tokens(词项)。这些tokens被存储在倒排索引中,以便后续搜索。
- **分析器应用:**在索引过程中,指定的分析器(由分词器和token过滤器组成)会被应用到字段上,以确定如何将文本分割成tokens。
(2)查询阶段(Query Phase)
- **查询解析:**当执行搜索查询时,Elasticsearch会对查询文本应用与索引时相同的分析器,包括分词器。这意味着查询文本也会被转换成tokens。
- **查询处理:**查询的tokens与索引的倒排索引中的tokens进行匹配,以确定哪些文档包含这些tokens。
(3)相关性评分(Scoring Phase)
- **评分计算:**在查询过程中,Elasticsearch会根据tokens在文档中出现的次数和频率计算相关性评分。分词器的使用确保了查询tokens与索引tokens的一致性,从而使得评分准确。
(4)聚合(Aggregations)
- **术语聚合:**在执行基于术语的聚合(如terms聚合)时,分词器确保了聚合字段的tokens与查询tokens的一致性。
(5)高亮(Highlighting)
- **结果高亮:**在搜索结果中,Elasticsearch会使用与索引相同的分析器对查询文本进行分词,以便在文档中高亮显示匹配的tokens。
(6)建议(Suggestions)
- **自动完成和建议:**在自动完成或建议功能中,分词器用于处理用户输入的查询,以便与索引中的tokens匹配。
(7)同义词处理(Synonyms)
- **查询扩展:**在使用同义词时,分词器可以与同义词过滤器结合使用,以便在查询时扩展tokens,包括同义词。
4、使用分词器
(1)默认分词器
- Elasticsearch的默认分词器是
standard
分词器。这个分词器适用于大多数西方语言,特别是英文,它基于Unicode文本分割算法(Unicode Text Segmentation)来分割文本,并去除大多数标点符号。standard
分词器在处理文本时会将所有单词转换为小写,以便进行不区分大小写的匹配。
- 在创建新的索引时,如果不指定分词器,Elasticsearch会自动使用
standard
分词器来处理文本字段。例如,如果你创建了一个名为my_index
的索引,并且没有指定分析器,那么my_index
中的text
字段将默认使用standard
分词器。
- 使用分词器进行分词,默认分词器无法解析中文词组,所以全部分词成单个字。
json
复制代码
# 请求
Get _analyze
{
"text":"测试分词器"
}
# 返回
{
"tokens" : [
{
"token" : "测",
"start_offset" : 0,
"end_offset" : 1,
"type" : "<IDEOGRAPHIC>",
"position" : 0
},
{
"token" : "试",
"start_offset" : 1,
"end_offset" : 2,
"type" : "<IDEOGRAPHIC>",
"position" : 1
},
{
"token" : "分",
"start_offset" : 2,
"end_offset" : 3,
"type" : "<IDEOGRAPHIC>",
"position" : 2
},
{
"token" : "词",
"start_offset" : 3,
"end_offset" : 4,
"type" : "<IDEOGRAPHIC>",
"position" : 3
},
{
"token" : "器",
"start_offset" : 4,
"end_offset" : 5,
"type" : "<IDEOGRAPHIC>",
"position" : 4
}
]
}
json
复制代码
# 请求
Get _analyze
{
"text":"测试分词器",
"analyzer": "ik_max_word"
}
# 返回
{
"tokens" : [
{
"token" : "测试",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "分词器",
"start_offset" : 2,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "分词",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "器",
"start_offset" : 4,
"end_offset" : 5,
"type" : "CN_CHAR",
"position" : 3
}
]
}
(2)创建索引并指定分析器
- 我们创建了一个名为
my_custom_analyzer
的自定义分析器,它使用standard
分词器,并且应用了lowercase
和asciifolding
过滤器。
- 我们将
text
字段的分析器设置为定义的my_custom_analyzer
。
json
复制代码
# 请求
PUT /my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "asciifolding"]
}
}
}
},
"mappings": {
"properties": {
"text": {
"type": "text",
"analyzer": "my_custom_analyzer"
}
}
}
}
# 返回
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "my_index"
}
(3)索引文档
text
字段的值会被my_custom_analyzer
处理,包括分词、小写化和ASCII折叠。
json
复制代码
# 请求
POST /my_index/_doc
{
"text": "Elasticsearch is a distributed search engine."
}
# 返回
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "mhUp05MBwu_sOZK4ykdt",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
(4)执行搜索
- 在这个搜索查询中,我们指定了
my_custom_analyzer
来处理查询字符串"Elasticsearch",确保查询时的分词和索引时的分词一致。
json
复制代码
# 请求
GET /my_index/_search
{
"query": {
"match": {
"text": {
"query": "Elasticsearch",
"analyzer": "my_custom_analyzer"
}
}
}
}
# 返回
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "mhUp05MBwu_sOZK4ykdt",
"_score" : 0.2876821,
"_source" : {
"text" : "Elasticsearch is a distributed search engine."
}
}
]
}
}
(5)注意事项
- 分析器的选择对搜索结果有重要影响。正确的分析器可以帮助提高搜索的相关性和准确性。
- 自定义分析器可以根据具体需求组合不同的分词器和过滤器。
- 在创建索引后,分析器的设置不能更改,除非重新创建索引。