Elasticsearch Analyzer内部机制

Analyzer的组成、执行过程以及各种analyzers。

一、Analyzer组成

  Analyzer 一般由三部分构成,character filters、tokenizers、token filters。掌握了 Analyzer 的原理,就可以根据我们的应用场景配置 Analyzer。
  Elasticsearch 有10种分词器(Tokenizer)、31种 token filter,3种 character filter,一大堆配置项。此外,还有还可以安装 plugin 扩展功能。这些都是搭建 analyzer 的原材料。

二、Analyzer执行过程

  Analyzer 的内部就是一条流水线
  • Step 1 字符过滤(Character filter)
  • Step 2 分词(Tokenization)
  • Step 3 Token 过滤(Token filtering)
analyzer_pipeline.svg

  Elasticsearch 已经默认构造了 8个 Analyzer。若无法满足我们的需求,可以通过 Setting API 构造 Analyzer。
  下面看一个例子:

PUT /my-index/_settings
{
  "index": {
    "analysis": {
      "analyzer": {
        "customHTMLSnowball": {
          "type": "custom",
          "char_filter": [
            "html_strip"
          ],
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "stop",
            "snowball"
          ]
        }
      }
    }
  }
}

  以上自定义的 Analyzer名为 customHTMLSnowball, 代表的含义:
  • 移除 html 标签 (html_strip character filter),比如 <p> <a> <div>
  • 分词,去除标点符号(standard tokenizer)
  • 把大写的单词转为小写(lowercase token filter)
  • 过滤停用词(stop token filter),比如 「the」 「they」 「i」 「a」 「an」 「and」。
  • 提取词干(snowball token filter,snowball 雪球算法 是提取英文词干最常用的一种算法)。
    cats -> cat
    catty -> cat
    stemmer -> stem
    stemming -> stem
    stemmed -> stem
  给定如下原文本:

The two <em>lazy</em> dogs, were slower than the less lazy <em>dog</em>.

  下面通过 customHTMLSnowball 这个分析器对源文本进行管道传输,它是这样处理的:
a_custom_analyzer.png

三、选择合适的Analyzer

1. 处理英文

  当我们的搜索场景为:英文博文、英文新闻、英文论坛帖等大段的文本时,最好使用包含 stemming token filter 的 analyzer。
  常见的 stemming token filter 有这几种: stemmer, snowball, porter_stem
  拿 snowball token filter 举例,它把 sing/ sings / singing 都转化词干 sing。并且丢弃了「they」 「are」两个停用词。不管用户搜 sing、sings、singing, 他的搜索结果都是基于「sing」这个term,所得的结果集都一样。

GET _analyze
{
  "text": "I sing he sings they are singing",
  "analyzer": "snowball"
}

  经过 snowball 分析后得到:

{
  "tokens": [
    {"token": "i", "position": 0, ...},
    {"token": "sing", "position": 1, ...},
    {"token": "he", "position": 2, ...},
    {"token": "sing", "position": 3, ...},
    {"token": "sing", "position": 6, ...}
  ]
}

  词干提取在英文搜索种应用广泛,但是也有局限:
  • 词干提取对中文意义不大。
  • 搜索专业术语,人名时,词干提取反而让搜索结果变差。
  eg:flying fishfly fishing 意思差之千里,但经过 snowball 处理后的他们的词根(Term)相同 fli fish。
  当用户搜索「假蝇钓鱼」信息时,出来的却是「飞鱼」 的结果,搜索结果十分不理想。
  此类场景,建议使用精准搜索,采用简单的分词策略(不提取词干,只 lowercase)+ Fuzzy query 可能是更好的选择。

2. 处理中文

  对中文的处理我们需要借助一些插件(plugin),即第三方中文分词器。我会单独写一篇博文介绍中文分词器,点击查看

3. Searching Tokens Exactly 精准搜索

  当我们搜索用户名(username),商品分类(category),标签(tag)时,希望精准搜索。建索引时最好不要再分词、也不要提取词干,完全可以跳过 analyzer 这一步。
  可以在某个字段的 mapping 中指定 “index”: “not_analyzed”,从而直接把原始文本转为 term,我们知道,trem query是完全匹配查询。
  注意:老版本ES是这样的,从ES 5.X版本开始,已经没有 string 类型字段,反之以 keyword 和 text 代替,keyword存储数据时候,不会分词建立索引;text存储数据时候,会自动分词,并生成索引。

PUT people-info
{
  "mappings": {
    "children": {
      "properties": {
        "name": {
          "type": "string",
          "index": "not_analyzed"
        }
      }
    }
  }
}

4. 其他需求

  用的不多,需要的时候见官网。


原文
https://www.elastic.co/blog/found-text-analysis-part-1


  目录