Analysis

Analysis(文本分析) 是把全文本转换一系列单词(term/token)的过程,也叫分词

Analysis是通过Analyzer来实现的。可使用 Elasticsearch 内置的分析器, 或者按需定制化分析器

Analyzer 分析器组成

分析器是专门处理分词的组件,由三部分组成:

  • Character Filters: 针对原始文本处理,例如去除HTML
  • Tokenizer: 安装规则分词
  • Token Filter : 将切分的单词进行加工、小写,删除stopwords,增加同义词

image-20220709185729262

Character Filters

首先,字符串按顺序通过每个 字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将 & 转化成 and

Tokenizer

这一步就是把字符转变成一个个terms(单词)。简单的tokenize可以根据空格或者标点符号进行划分。例如:

Input: "I REALLy like beer!"
Output: ["I", "REALLY", "like", "beer"]

Token filters

在有了一个个terms之后,会进行最后的filter,比如把所有的单词都改成小写,或者同义词的变换,或者把一些禁止的词去除掉等等。例如:

Input: ["I", "REALLY", "like", "beer"]
Output: ["I", "really", "like", "beer"]

上述三个组件工作流程如下:

image-20220709190019511

Analyzer API - 测试分析器

Elasticsearch附带了可以直接使用的分析器。标准分析器(Standard Analyzer)是Elasticsearch默认使用的分析器。它是分析各种语言文本最常用的选择。它根据Unicode 联盟定义的 单词边界 划分文本。删除绝大部分标点, 最后将词条小写。

有些时候很难理解分词的过程和实际被存储到索引中的词条,特别是你刚接触Elasticsearch。为了理解发生了什么,你可以使用 analyze API 来看文本是如何被分析的。在消息体里,指定分析器和要分析的文本。例如,我们调用默认的分析器来分析一段文本:

POST /_analyze
{
  "text":"2 guys, a bar. ... DUCKS! :-)",
  "analyzer": "standard"
}

它将返回:

{
  "tokens": [
    {
      "token": "2",
      "start_offset": 0,
      "end_offset": 1,
      "type": "<NUM>",
      "position": 0
    },
    {
      "token": "guys",
      "start_offset": 2,
      "end_offset": 6,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "a",
      "start_offset": 8,
      "end_offset": 9,
      "type": "<ALPHANUM>",
      "position": 2
    },
    {
      "token": "bar",
      "start_offset": 10,
      "end_offset": 13,
      "type": "<ALPHANUM>",
      "position": 3
    },
    {
      "token": "ducks",
      "start_offset": 19,
      "end_offset": 24,
      "type": "<ALPHANUM>",
      "position": 4
    }
  ]
}

token 是实际存储到索引中的词条。 position 指明词条在原始文本中出现的位置。 start_offsetend_offset 指明字符在原始字符串中的位置。

image-20220716202223091

从结果上看,标准分析器将标点符号去除,并将大写转换成了小写。


当然我们可以指定使用不同的组件(char_filter, tokenizer, filter)来进行分析:

POST /_analyze
{
  "text":"2 guys, a bar. ... DUCKS! :-)",
   "char_filter": [],
   "tokenizer": "standard",
   "filter": ["lowercase"]
}

上面三个组件其实构成了standard analyzer,返回和上面一样的结果:

image-20220716202331644