ES[7.6.x]學習筆記(六)分析器

牛初九發表於2020-05-06

在前面的章節中,我們給大家介紹了索引中的對映型別,也就是每一個欄位都有一個型別,比如:long,text,date等。這和我們的資料庫非常的相似,那麼它的不同之處是什麼呢?對了,就是全文索引,在ES當中,只有text型別的欄位才會用的全文索引,那麼這裡就會引出ES中一個非常重要的概念,文字分析器(Text analysis)

分析器使ES支援全文索引,搜尋的結果是和你搜尋的內容相關的,而不是你搜尋內容的確切匹配。我們用ES官網中的例子給大家舉例,假如你在搜尋框中輸入的內容是Quick fox jumps,你想得到的結果是A quick brown fox jumps over the lazy dog,或者結果中包含這樣的詞fast foxfoxes leap

分析器之所以能夠使搜尋支援全文索引,都是因為有分詞器(tokenization),它可以將一句話、一篇文章切分成不同的詞語,每個詞語都是獨立的。假如你在ES索引中新增了一條記錄the quick brown fox jumps,而使用者搜尋時輸入的內容是quick fox,並沒有完全匹配的內容,但是因為有了分詞器,你索引的內容被切分成了不同的、獨立的詞,使用者搜尋的內容也會進行相應的切分,所以使用者搜尋的內容雖然沒有完全匹配,但也能夠搜尋到想要的內容。

分析器除了要做分詞,還要做歸一化(Normalization)。分詞器能夠使搜尋內容在每一個詞上匹配,但這種匹配也只是在字面上進行的匹配。

  • 比如你搜尋Quick,但是不能匹配到quick,它們的大小寫不同。
  • 比如你搜尋fox,但是不能匹配到foxes,它是複數形式。
  • 比如你搜尋jumps,不能匹配到leaps,雖然它們是同義詞。

為了解決這些問題,分析器要把這些分詞歸一化到標準的格式。這樣我們在搜尋的時候就不用嚴格的匹配了,相似的詞語我們也能夠檢索出來,上面的3種情況,我們也能夠搜尋出相應的結果。

分析器的組成

分析器,無論是內建的,還是自定義的,都是由3部分組成:字元過濾器(character filters)、分詞器(tokenizers)、分詞過濾器(token filters)。

字元過濾器

字元過濾器接收最原始的文件,並且可以改變其內容,比如:可以把中文的一二三四五六七八九,變成阿拉伯數字123456789。它還可以過濾html標籤,並對其進行轉義。還可以通過正規表示式,把匹配到的內容轉化成其他的內容。一個分析器可以有多個字元過濾器,也可以沒有字元過濾器。

分詞器

一個分析器只能有一個確定的分詞器,它可以把一句話分成若干個詞,比如:空格分詞器。當你輸入一句話Quick brown fox!,它將被切分成[Quick, brown, fox!]

分詞過濾器

分詞過濾器接收分詞並且可以改變分詞,比如:小寫分詞過濾器,它將接收到的分詞全部轉換成小寫。助詞過濾器,它將刪除掉一些公共的助詞,比如英語裡的 theisare等,中文裡的等。同義詞過濾器,它將在你的分詞中,新增相應的同義詞。一個分析器可以有多個分詞過濾器,它們將按順序執行。

我們在建立索引和搜尋時,都會用的分析器。

配置文字分析器

前面我們講了分析器的基本概念,也瞭解了全文搜尋的基本步驟。下面我們看一下如何配置文字分析器,ES預設給我們配置的分析器是標準分析器。如果標準的分析器不適合你,你可以指定其他的分析器,或者自定義一個分析器。

ES有分析器的api,我們指定分析器和文字內容,就可以得到分詞的結果。比如:

POST _analyze
{
  "analyzer": "whitespace",
  "text":     "The quick brown fox."
}

返回的結果如下:

{
    "tokens": [
        {
            "token": "The",
            "start_offset": 0,
            "end_offset": 3,
            "type": "word",
            "position": 0
        },
        {
            "token": "quick",
            "start_offset": 4,
            "end_offset": 9,
            "type": "word",
            "position": 1
        },
        {
            "token": "brown",
            "start_offset": 10,
            "end_offset": 15,
            "type": "word",
            "position": 2
        },
        {
            "token": "fox.",
            "start_offset": 16,
            "end_offset": 20,
            "type": "word",
            "position": 3
        }
    ]
}

我們指定的分析器是空格分析器,輸入的文字內容是The quick brown fox.,返回結果是用空格切分的四個詞。我們也可以測試分析器的組合,比如:

POST _analyze
{
  "tokenizer": "standard",
  "filter":  [ "lowercase", "asciifolding" ],
  "text":      "Is this déja vu?"
}

我們指定了標準的分詞器,小寫過濾器和asciifolding過濾器。輸入的內容是Is this déja vu?,我們執行一下,得到如下的結果:

{
    "tokens": [
        {
            "token": "is",
            "start_offset": 0,
            "end_offset": 2,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "this",
            "start_offset": 3,
            "end_offset": 7,
            "type": "<ALPHANUM>",
            "position": 1
        },
        {
            "token": "deja",
            "start_offset": 8,
            "end_offset": 12,
            "type": "<ALPHANUM>",
            "position": 2
        },
        {
            "token": "vu",
            "start_offset": 13,
            "end_offset": 15,
            "type": "<ALPHANUM>",
            "position": 3
        }
    ]
}

我們可以看到結果中,is變成了小寫,déja變成了deja,最後的?也過濾掉了。

為指定的欄位配置分析器

我們在建立對映時,可以為每一個text型別的欄位指定分析器,例如:

PUT my_index
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "whitespace"
      }
    }
  }
}

我們在my_index索引中,建立了title欄位,它的型別是text,它的分析器是whitespace空格分析器。

為索引指定預設的分析器

如果我們覺得為每一個欄位指定分析器過於麻煩,我們還可以為索引指定一個預設的分詞器,如下:

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default": {
          "type": "whitespace"
        }
      }
    }
  }
}

我們為my_index索引指定了預設的分析器whitespace。這樣我們在建立text型別的欄位時,就不用為其指定分析器了。

這一節給大家介紹了分析器,我們可以看到例子中都是使用的英文分析器,下一節我們一起看一下強大的中文分析器。

相關文章