Elasticsearch中ngram和edgengram分詞器


 


1. Analysis 簡介

理解elasticsearch的ngram首先需要了解elasticsearch中的analysis。在此我們快速回顧一下基本原理:

當一個文檔被索引時,每個field都可能會創建一個倒排索引(如果mapping的時候沒有設置不索引該field)。倒排索引的過程就是將文檔通過analyzer分成一個一個的term,每一個term都指向包含這個term的文檔集合。當查詢query時,elasticsearch會根據搜索類型決定是否對query進行analyze,然后和倒排索引中的term進行相關性查詢,匹配相應的文檔

analyzer = CharFilters(0個或多個) + Tokenizer(恰好一個) + TokenFilters(0個或多個)

2. index analyzer VS search analyzer

如果mapping中只設置了一個analyzer,那么這個analyzer會同時用於索引文檔和搜索query。當然索引文檔和對query進行analysis也可以使用不同的analyzer

一個特殊的情況是有的query是需要被analyzed,有的並不需要。例如match query會先用search analyzer進行分析,然后去相應field的倒排索引進行匹配。而term query並不會對query內容進行分析,而是直接和相應field的倒排索引去匹配

3. Analyze API

Analyze API是一個有效的方式查看分析后的結果:

POST _analyze
{
    "analyzer" : "standard",
    "text" : "hello, world"
}

輸出的結果如下所示,即[hello, world]

4. Ngram

在機器學習和數據挖掘領域,ngram通常指的是n個詞的序列。不過在elasticsearch中,ngram代表的是n個字符的序列。可以把ngram理解成長度為n的滑動窗口,在文檔中滑動產生的序列

5. Ngram Tokenizer

POST _analyze
{
  "tokenizer": "ngram",
  "text": "Quick Fox"
}

ngram分詞器默認會產生最小長度為1,最大長度為2的N-grams序列。上述查詢語句的輸出是
[ Q, Qu, u, ui, i, ic, c, ck, k, "k ", " “, " F”, F, Fo, o, ox, x ]

也可以自定義ngram tokenizer的一些配置:

  • min_gram: 指定產生的最小長度的字符序列,默認為1

  • max_gram: 指定產生的最大長度的字符序列,默認為2

  • token_chars: 指定生成的token應該包含哪些字符.對沒有包含進的字符進行分割,默認為[],即保留所有字符

  • letter - eg: a,b,字
  • digit - eg: 3,7
  • whitespace - eg: " ", “\n”
  • punctuation - eg: !, "
  • symbol - eg: $,√

定義min_grammax_gram應該按照使用場景來定。使用ngram的一個常見場景就是自動補全。如果單個字符也進行自動補全,那么可能匹配的suggestion太多,導致沒有太大意義。
另一個需要考慮的便是性能,產生大量的ngram占用空間更大,搜索時花費的事件也更多。

假如現在需要將ngrams生成的token都轉換成小寫形式,可以使用如下形式

PUT my_index
{
   "settings": {
      "analysis": {
         "tokenizer": {
            "ngram_tokenizer": {
               "type": "nGram",
               "min_gram": 4,
               "max_gram": 4,
               "token_chars": [ "letter", "digit" ]
            }
         },
         "analyzer": {
            "ngram_tokenizer_analyzer": {
               "type": "custom",
               "tokenizer": "ngram_tokenizer",
               "filter": [
                  "lowercase"
               ]
            }
         }
      }
   }
}
POST my_index/_analyze
{
  "analyzer": "ngram_tokenizer_analyzer",
  "text": "Hello, World!"
}
生成的結果序列是[ello, hell, orld, worl]

6. Ngram Token Filter

上述的例子也可以使用Ngram Token Filter,配上standard的分詞器和lower-case的過濾器。
原文本被standard分詞器以whitespace和punctuation分割成token,然后通過lowercase過濾器轉換成小寫形式,最后通過ngram filter生成長度為4的字符序列

PUT /my_index
{
   "settings": {
      "analysis": {
         "filter": {
            "ngram_filter": {
               "type": "nGram",
               "min_gram": 4,
               "max_gram": 4
            }
         },
         "analyzer": {
            "ngram_filter_analyzer": {
               "type": "custom",
               "tokenizer": "standard",
               "filter": [
                  "lowercase",
                  "ngram_filter"
               ]
            }
         }
      }
   }
}

POST my_index/_analyze
{
  "analyzer": "ngram_filter_analyzer",
  "text": "Hello, World!"
}

上述mapping也會和ngram tokenizer產生同樣的效果,具體實際應用如何選擇應該視場景而定。假如想匹配的term中可以包含特殊字符,那么你應該使用ngram tokenizer。因為standard的tokenizer會過濾掉這些特殊字符。

7. Edge Ngram

Edge Ngram和ngram類似,只不過Edge Ngram產生的序列都是從代索引文檔的開頭延伸出去的。

POST _analyze
{
  "tokenizer": "edge_ngram",
  "text": "Quick Fox"
}

會產生[ Q, Qu ]

Edge Ngram也有着和ngram相同的配置

  • min_gram: 指定產生的最小長度的字符序列,默認為1

  • max_gram: 指定產生的最大長度的字符序列,默認為2

  • token_chars: 指定生成的token應該包含哪些字符.對沒有包含進的字符進行分割,默認為[],即保留所有字符

  • letter - eg: a,b,字
  • digit - eg: 3,7
  • whitespace - eg: " ", “\n”
  • punctuation - eg: !, "
  • symbol - eg: $,√
    對於如下的mapping
PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  }
}
POST my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "2 Quick Foxes."
}

 

 

產生的token序列為[ Qu, Qui, Quic, Quick, Fo, Fox, Foxe, Foxes ]

參考連接:
https://njucz.github.io/2017/12/20/elasticsearch%20ngram,edgengram%E7%AC%94%E8%AE%B0/

https://blog.csdn.net/xixihahalelehehe/article/details/115302683


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM