iT邦幫忙

2024 iThome 鐵人賽

DAY 0
0
自我挑戰組

重新開始 elasticsearch 系列 第 5

2024 鐵人賽 Day6: Text Analyzer I

  • 分享至 

  • xImage
  •  

Inverted index

前一篇說到 ES 會對 type 是 text 的 field 進行文字分析後供全文檢索,在說明『文字分析』確切是什麼之前,要先解釋一下 inverted index(倒排索引)這個概念;當初我在學 ES 的時候,是從『使用』開始的,在使用上遇到了很多跟我想像不一樣的結果,在理解 inverted index 後,覺得打通了很多不理解的部分,如果你希望可以跟 ES 相處順利,這個概念不要跳過喔~

想像一下在電腦普及之前的倉庫裡,放眼望去有無止盡的貨架,貨架上有諸多種類的產品放在比貨品大很多的的紙箱中,今天因為公司規定的更改,任何含有『酒精』成分的產品需要被搬移到另外的倉庫,目前管理的文件中對於倉儲物品的紀錄是表格化的,寫著以貨品為單位的資訊,成分那一欄是隨意長度的手寫文字;也就是很像這樣:

貨品名稱 倉儲位置 成分 大小 重量 分類
玻璃水杯 C4102 物品:矽、包裝:紙 12 * 4* 4.5 210g 日用品

此時,如果有一個表格根據 {成分:物品清單} 這件事就會很快被解決了。

inverted index 就是這個 {成分: 物品清單} 的紀錄方法,將資料切分成元素,把元素當作 key 值,紀錄哪些資料包含這個元素,在透過元素找資料的時候就會相對快速。

在文本處理的領域,把文本(一串字)切成元素的步驟稱為分詞(tokenize),切出來的元素(通常是表意的詞)稱為 token。inverted index 套用在文本搜尋索引上就是把文本切成很多個 token 之後,拿 token 當 key,紀錄 token 出現在哪些文本裡。

以下為一個簡單的例子(內容是從 Elastic 官網隨機擷取的):

以下為三個文本

文本編號 1:retrieve selected fields from a search

文本編號 2:to retrieve specific fields in the search response

文本編號 3:use the fields parameter

針對三個文本進行 reverted index 的內容大概是這樣:

retrive: 1, 2

selected: 1

fields: 1, 2, 3

…(略)

paramater: 3

有了 inverted index,當文本增加到至成千上萬的時候,要知道哪個文本有 parmater 這個詞的時候就相當的容易了。

Analyzer

由此可以發現,怎麼把文本處理成要進行 reveted index 的 token 是會顯著影響搜尋的,例如根據上面的例子,如果搜尋『field』是會找不到東西的,因為只有『 fields』有被 index。

在文本資料處理中,除了 tokenize,還有很多其他的工程或是資料清理步驟讓資料變的更符合使用目的(目的不一定只是搜尋),例如定義停頓詞(stop-words)、同義詞、正規化(大小寫等同、複數型)等,也就是前述『文字分析』的部分。而這個部分 ES 會讓文本在被 index 前通過 Analyzer 來處理。

Analyzer 可以由三個成分組成,其中只有 tokenizer 是必要的:

  • character filter:在進分詞器前,哪些字要被預先處理(例如忽略或置換)
  • tokenizer:分詞器
  • token filter:在分詞後,哪些 token 要被進行後處理(例如全部轉小寫)

這三個成分各自代表一種文字的處理,並且會依照上列的順序進行,也就是先以一個 document 為單位,進行文字的處理(character filter) → 分詞(tokenizer) → 以分詞為單位進行後處理(token filter)。

ES 根據不同的場景有內建幾個 Analyzer 可以直接使用,而組成內建 Analyzer 的這三個成分,你也可以自己來拿組合成自己的 Analyzer;當然如果要自己建造一個全新 Analyzer 的也沒有問題。

以下是一個簡單的例子,在 settins / analysis / analyzer 中定義了 my_customer_analyzer ,並於 description 這個 fields 使用 my_customer_analyzer 進行索引時的文字分析。

PUT my-index-000001
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "char_filter": [
            "html_strip"
          ],
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "description": {
        "type": "text",
        "analyzer": "my_custom_analyzer"
        }
    }
  }
}

除了上面三項,Analyzer 還有以下兩個其他設定:

  • type:可以從這個列表中選一個(內建的),或是使用 custom 表示為自訂的。
  • position_increment_gap:在 ES 內,文字在文本中的距離(間隔幾個字)是有意義的,當索引的欄位是文字陣列(array of text)時,ES 會預設陣列元素之間的距離是 100;這個參數可以調整文字陣列元素之間距離的預設值。舉例如下:
    • [”alpaca Mori” , “llama Vendy”, “monkey Joe”],alpaca 和 Mori 的距離是 1,但在預設參數下,alpaca 距離 llama 是 101,會使得 array 間 token 的距離相較於元素內的 token 來的遠。
    • 這個參數會搭配 match_phrase query 中的 slop 參數使用。

下一篇文章會說明如何設定自訂義(custom)的 Analyzer。


上一篇
2024 鐵人賽 Day5: Index Mapping
下一篇
2024 鐵人賽 Day7: Text Analyzer II
系列文
重新開始 elasticsearch 29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言