什么是分词器?
顾名思义,文本分析就是把全文本转换成一系列单词(term/token)的过程,也叫分词。在 ES 中,Analysis 是通过分词器(Analyzer) 来实现的,可使用 ES 内置的分析器或者按需定制化分析器。
他有什么功能?可以做什么?
分词器的主要作用将用户输入的一段文本,按照一定逻辑,分析成多个词语的一种工具。 举一个分词简单的例子:比如你输入 Mastering Elasticsearch,会自动帮你分成两个单词,一个是 mastering,另一个是 elasticsearch,可以看出单词也被转化成了小写的。
Analyzer
Elasticsearch 可以实现秒级的搜索速度,其中很重要的一个原因就当一个文档被存储的时候,同时它也对文档的数据进行了索引(indexing)。这样在以后的搜索中,就可以变得很快。简单地说,当一个文档进入到 Elasticsearch 时,它会经历如下的步骤:
中间的那部分就叫做 Analyzer。我们可以看出来,它分为三个部分:Char Filters, Tokenizer 及 Token Filters。
下图显示了一个解释分析过程的示例。
它们的作用分别如下:
Char Filters(字符过滤器): 字符过滤器的工作是执行清除任务,将原始文本作为字符流接收,并可以通过添加、删除或更改字符来转换流。例如剥离 HTML 标记,词项处理将印度-阿拉伯数字 (٠ ١٢٣٤٥٦٧٨ ٩ ) 转换为阿拉伯-拉丁语等价物 (0123456789)等。分词器可能有零个或多个字符过滤器,它们按顺序应用
Tokenizer(分词器): 接收字符流,将其分解为单独的 tokens(通常是单个单词),并输出 tokens 流。 例如,whitespace 分词器在看到任何空格时将文本分解为tokens。 它会将文本“Quick brown fox!”转换为terms[Quick, brown, fox!]。tokenizer分词器还负责记录每个词条的顺序或位置,以及该词条所代表的原始单词的开始和结束字符偏移量。分词器必须具有正好一个 tokenizer。
Token filters(词项过滤器): 一旦创建了 token,它们就会被传递给 token filters,这些过滤器会对 token 进行规范化。 Token filters 可以更改 token,删除术语或向 token 添加术语。
请注意,字符和标记过滤器都是可选的,但我们必须有一个分词器。
一个 analyzer 有且只有一个 tokenizer,有0个或一个以上的 char filter 及 token filter。
在默认的情况下,standard analyzer 是 Elasticsearch 的缺省分析器:
- 没有 Char Filter
- 使用 standard tokonizer
- 把字符串变为小写,同时有选择地删除一些 stop words 等。默认的情况下 stop words 为 none,也即不过滤任何 stop words。
Elasticsearch 已经提供了比较丰富的 analyzer。我们可以自己创建自己的 token analyzer,甚至可以利用已经有的 char filters,tokenizer 及 token filters 来重新组合成一个新的 analyzer,并可以对文档中的每一个字段分别定义自己的 analyzer。
自带分词器
| 分析器 | 描述 | 分词对象 |
|---|---|---|
| standard | 标准分析器是默认的分析器,如果没有指定,则使用该分析器。它提供了基于文法的标记化(基于 Unicode 文本分割算法,如 Unicode 标准附件 # 29所规定) ,并且对大多数语言都有效。 | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. |
| simple | 简单分析器将文本分解为任何非字母字符的标记,如数字、空格、连字符和撇号、放弃非字母字符,并将大写字母更改为小写字母。 | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. |
| whitespace | 空格分析器在遇到空白字符时将文本分解为术语 | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. |
| stop | 停止分析器与简单分析器相同,但增加了删除停止字的支持。默认使用的是 english 停止词。 | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. |
| keyword | 不分词,把整个字段当做一个整体返回 | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. |
| pattern | 模式分析器使用正则表达式将文本拆分为术语。正则表达式应该匹配令牌分隔符,而不是令牌本身。正则表达式默认为 w+ (或所有非单词字符)。 | The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. |
| ik_smart | k分词器中的简单分词器,支持自定义字典,远程字典 | 学如逆水行舟,不进则退 |
| ik_max_word | ik_分词器的全量分词器,支持自定义字典,远程字典 | 学如逆水行舟,不进则退 |
索引和搜索分词
analyzer 执行将输入字符流分解为token的过程,它一般发生在两个场合:
- 在 indexing 的时候,也即在建立索引的时候,默认会索引时分词
- 在 searching 的时候,也即在搜索时,分析需要搜索的词语,需要指定search_analyzer字段
样例:
索引数据时分词:
PUT my_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "whitespace"
}
}
}
}
搜索时分词
PUT my_index2
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "whitespace",
"search_analyzer": "simple"
}
}
}
}
测试分词
如何自定义分词器
| 参数 | 描述 |
|---|---|
| tokenizer | 内置或定制的tokenizer.(必须) |
| char_filter | 内置或定制的char_filter(非必须) |
| filter | 内置或定制的token filter(非必须) |
| position_increment_gap | 当值为文本数组时,设置改值会在文本的中间插入假空隙。设置该属性,对与后面的查询会有影响。默认该值为100. |
样例:
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"char_filter": [
"html_strip"
],
"filter": [
"lowercase"
]
}
}
}
}
}
该分词器的type为custom,tokenizer为standard,char_filter为hmtl_strip,filter定义了两个分别为:lowercase和asciifolding。这个分词器的主要作用就是过滤html标签,转成文本存起来
定义复杂分词器
PUT /ablogs
{
"settings": {
"index": {
"number_of_shards": "1", # 索引的主分片数,默认值是 51024。
"number_of_replicas": "1", # 索引主分片的副本数,默认值是 1,
"provided_name": "article_news_2019-01",
# 执行新索引数据的刷新操作频率
"refresh_interval": "60s",
"analysis": {
#定制化分析器
"analyzer": {
#自定义分析器名称
"my_custom_analyzer": {
"type": "custom",
"char_filter": [
"xgame_filter"
],
"tokenizer": "standard",
"filter": [
"lowercase",
"my_stop"
]
}
},
#自定义char_filter实现
"char_filter": {
"xgame_filter": {
"type": "mapping",
"mappings": [
"X-Game => XGame"
]
}
},
#自定义filter实现
"filter": {
"my_stop": {
"type": "stop",
"stopwords": [
"so",
"to",
"the"
]
}
}
}
}
},
#定义mapping
"mappings": {
#索引的type
"_doc": {
"properties": {
"content": {
"type": "text",
#指定分析器
"analyzer": "my_custom_analyzer"
#指定查询分析器
"search_analyzer": "standard"
}
}
}
}
}