Elasticsearch 分析(Analysis)
什么是 Analysis(分析)
Analysis 是指对全文本(Full Text)进行分词,以便生成供搜索用的倒排索引。
这个过程是由 analyzer(分析器) 来完成的。
分析器(Analyzer)
分析器主要包含三个组成部分。
- 字符过滤器
- 分词器
- 标记过滤
字符过滤器(Character Filter) : 文本字符串首先会经过字符过滤器的预处理,过滤掉无用的字符(如 HTML 标记),将 “&” 转换为 “and” 等。
分词器(Tokenizer) : 能够将字符串拆分为一个个独立的 token 或 term。
过滤器(Filter) : 经过分词器处理后的一系列 token ,可以由过滤器再次进行处理。比如,修改 token(转换为小写)、删除无用的 token(如 the)、增加同义词等等。
分词器(Tokenizer)
Tokenizer 是 Analyzer 最重要的组成部分。
Elasticsearch 中有很多内置的 Tokenizer,我们可以用它来创建自定义的 Analyzer。
这些内置的 Tokenizer,可以分为三大类:
- 单词分词器
- 局部单词分词器
- 结构化文本分词器
单词分词器
单词分词器(Word Tokenizer)主要用于将全文本拆分为独立的单词。
单词分词器主要包含以下几种:
- Standard Tokenizer(标准分词器):基于单词边界将文本拆分为独立的项,它会删除大多数标点符号。
- Letter Tokenizer(字母分词器):拆分文本时,如果遇到非字母就进行拆分。
- Lowercase Tokenizer(小写字母分词器):和字母分词器类似,它还会将拆分后的项转化为小写字母。
- Whitespace Tokenizer(空格分词器):顾名思义,拆分文本时,如果遇到任何空格就进行拆分。
- UAX URL Email Tokenizer(URL & Email分词器):和标准分词器类似,它还可以对 URL 和 Email 进行拆分。
- Classic Tokenizer(经典分词器):根据英文语法来拆分文本。
- Thai Tokenizer(泰文分词器):根据泰文语法来拆分文本。
局部单词分词器
局部单词分词器(Partial Word Tokenizer)可用于根据将文本或单词拆分为更小的片段。
它主要包含一些几种:
- N-Gram Tokenizer:基于指定的特殊字符(如空格、标点符号),将文本拆分为独立的词,并返回词的局部片段。如:quick → [qu, ui, ic, ck]。
- Edge N-Gram Tokenizer:基于指定的特殊字符(如空格、标点符号),将文本拆分为独立的词,并返回词的局部片段。如:quick → [q, qu, qui, quic, quick]。
结构化文本分词器
结构化文本分词器(Structured Text Tokenizer)可用于处理结构化的特殊文本,如身份证号、电子邮箱、邮编、路径等。
- Keyword Tokenizer(关键字分词器):它可以处理任何文本,并将其作为确切的独立项返回。关键字分词器可以结合过滤器一起使用,将独立的项标准化为小写。
- Pattern Tokenizer(正则分词器):它可以基于正则表达式的匹配项来拆分特殊文本。
- Path Tokenizer(路径分词器):根据路径的层次结构对路径进行分词。如:文件系统的路径,/foo/bar/baz → [/foo, /foo/bar, /foo/bar/baz ]。
自定义分析器
如果 Elasticsearch 内置的 Analyzer 无法满足你的需求,你就可以自定义分析器(Custom Analyzer)。
自定义分析器通常包含:
- 0 个或多个字符过滤器(Character Filter)
- 1 个分词器(Tokenizer)
- 0 个或多个过滤器(Filter)
如下,是一个给索引库设置自定义分析器的示例:
PUT /my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"char_filter": [
"html_strip"
],
"filter": [
"lowercase",
"asciifolding"
]
}
}
}
}
}
返回结果:
{
"acknowledged": true,
"shards_acknowledged": true
}
我们来测试上面的自定义分析器。
POST /my_index/_analyze
{
"analyzer": "my_custom_analyzer",
"text": "<b>Is this your dog</b>?"
}
返回结果:
{
"tokens": [
{
"token": "is",
"start_offset": 3,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "this",
"start_offset": 6,
"end_offset": 10,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "your",
"start_offset": 11,
"end_offset": 15,
"type": "<ALPHANUM>",
"position": 2
},
{
"token": "dog",
"start_offset": 16,
"end_offset": 23,
"type": "<ALPHANUM>",
"position": 3
}
]
}
上面自定义的那个分析器,用到的 char_filter、tokenizer 和 filter 其实都是它们的默认配置。这里,我们来自定义一个复杂的分析器。
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_"
}
}
}
}
}
内置分析器
我们知道,分词器是分析器的主要组成部分,而 Elasticsearch 内置了多种分词器,那么对应的,也内置了多种分析器。
这里,我们就简单介绍一个内置分析器。
标准分析器
标准分析器(standard analyzer)是默认的分析器。
它由以下几个部分组成:
- Standard Tokenizer(标准分词器)
- Filters(过滤器):Standard Token Filter、Lower Case Token Filter 和 Stop Token Filter(默认禁用状态)。
测试分析器
为了便于理解各种分析器是如何工作的,我们可以对分析器进行测试。
测试内置的标准分析器。
GET /_analyze
{
"analyzer": "standard",
"text": "2 Brown-Foxes jumped over the lazy dog's bone."
}
说明: 由于携带交互数据(请求体)的 GET 请求并不被广泛支持,RFC 也并未明文禁止 GET 请求携带交互数据。而 Elasticsearch 的作者更倾向于用 GET 提交查询请求,因此,Elasticsearch 所有的查询 API 同样也支持 POST 方式。
故上面的示例也可以这样写:
POST /_analyze
{
"analyzer": "standard",
"text": "2 Brown-Foxes jumped over the lazy dog's bone."
}
索引时分析器
可以给文档的字段指定具体的分析器。如下:
# 给 my_index/my_type 中的 title 字段指定标准分析器
PUT /my_index
{
"mappings": {
"my_type": {
"properties": {
"title": {
"type": "text",
"analyzer": "standard"
}
}
}
}
}
当 Elasticsearch 对 my_index/my_type 中的文档建立索引时,如果没有指定分析器,就会使用索引库的分析器配置,如果索引库也没有配置分析器,就会使用默认的标准分析器。
搜索时分析器
同样的分析过程也适用于全文搜索时的查询字符串。
例如,match 查询时,要搜索的字符串文本会被切分为单个独立的项。
GET /_search
{
"query": {
"match" : {
"message" : "a quick fox"
}
}
}
分词结果:
“a quick fox” → [a, quick, fox ]
通常,全文搜索将使用和索引字段时相同的分析器来分析查询字符串。
搜索特殊字段的分析器取决于下面的顺序:
- 查询字符串本身指定的分析器
- mapping 中的 search_analyzer 选项
- mapping 中的 analyzer 选项
- 索引库的 default_search 配置项
- 索引库的 default 配置项
- 标准分析器
中文分析器
最常用的中文分析器(analyzer)插件是 ik。
详情请参考它的 GitHub 地址。
参考文献
[1] https://www.elastic.co/guide/en/elasticsearch/reference/5.2/index.html
还没有评论,来说两句吧...