iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
Software Development

30 天學習 Elasticsearch系列 第 18

Day 18 Elasticsearch - 使用 Analyze API 以及 Inverted indices

  • 分享至 

  • xImage
  •  

該文章同步發佈於:我的部落格

也歡迎關注我的 Facebook 以及 Instagram 接收軟體相關的資訊!

上一篇文章 介紹完 analyzer 之後,還是要來實際地使用看看 API,這篇文章也會順便解釋一下 Inverted indices 是什麼?

使用 Analyze API

使用起來非常簡單,這是 Elasticsearch ( 以下簡稱 ES ) 提供我們測試內容分析後結果的一個 API。

使用 POST /_analyze 接著輸入要被分析的語句,這邊使用一部電影的台詞做示範:

No point in punching things you can’t see.” Cinderella Man (2005) – James Braddock ( Russell Crowe )

然後使用的 analyzer 是 standard,根據 上一篇文章 中有提過 analyzer 的三個組件,這邊預設的 standard 是使用哪三個呢?別急,我們等等會做個實驗。

下圖就是送出請求後得到的回覆:

一張圖片沒辦法截完,但每一個 token 的結構都是長下面這樣:

{
  "token": "in",
  "start_offset": 9,
  "end_offset": 11,
  "type": "<ALPHANUM>",
  "position": 2
}

除了 token 本身的 in 之外,還可以看到一些額外的 metadata,像是 start_offset 以及 end_offset 就提供了該 token 在原始詞句中的位置,這有助於 ES 提供一些有趣的功能,像是文字的 highlight。

type 則是這個 token 在這個 tokenizer 底下被分配的類別,以 standard 的 analyzer 來說,主要有 ALPHANUM , NUM , IDEOGRAPHIC 這幾種類型,但具體還是需要看使用的 tokenizer 提供什麼樣的 type

好的,現在對於使用 analyze 的 API 應該是有一點概念了,接著我們可以把 analyzer 拆分成三個組件去呼應 上一篇文章 提到的內容,如下圖:

回應的結果還是和原本的一模一樣,你可以自己試試看!

這樣我們就知道,standard 的 analyzer 的組成是:

  1. 沒有使用任何的 character filter
  2. 使用了 standardtokenizer
  3. 使用了 lowercasetoken filter ( 這邊 API 的 payload 直接使用 filter 就可以了 )

所以基本上所有的分析核心都是在 standard 的 tokenizer 裡面,那它到底做了什麼呢?簡單來說大概就三點:

  1. 字詞拆分,根據 Unicode Text Segmentation Algorithm 這套演算法去處理如何把句子有意義地拆分成字詞。
  2. 數字辨識:數字和浮點數也會被視為單獨的 token。
  3. 標點符號和特殊符號移除:大多數的標點符號和其他非字母數字符號會被移除,除非它們位於數字或字母之間,像是在 email 中間的 @ 就不會被移除。

在知道 Analyzer 以及如何使用 analyze API 之後,就要把這些 tokens 給儲存起來,關於 text 的資料類型,ES 是使用 Inverted indices 的資料結構去儲存的。

Inverted Indices

俗稱倒排索引,也可以叫做反向索引,至於反在哪?往下看就知道了。

主要就是在紀錄 單字 以及 documents 之間的關聯。

舉一個簡單的例子,My name is Robert. 這段句子,經過基本的分析過後,會變成:

["my", "name", "is", "robert"]

這時候,ES 就會建立一個本子,記錄下來這樣的格式:

這樣大概對於為什麼叫做 反向索引 有一點感覺了吧?正常邏輯下的索引都會以 document 為主體,去儲存它含有哪些單字,但那樣對於全文搜尋來說太慢太弱了,反向索引 才是典型搜尋引擎演算法中重要的一個部分。

接著假設繼續加入一些資料,像是 Robert is a man 以及 That is a good name 這兩個句子好了。

結構圖就會變成這樣:

這時候,當我們搜尋 robert 時,ES 就會知道 document#1 以及 document#2 裡面有這個單字。

現在你可能會有點疑惑,這些資料到底在指什麼呢?我們現在討論的脈絡都是在 document 上的某一個欄位,像是上面這三個句子,可以是 Chats 這個 index 其中 3 個 documents 的 message 欄位。

//document#1
{
  ...
  "_source": {
    "message": "My name is Robert."
  }
}

// document#2
{
  ...
  "_source": {
    "message": "Robert is a man"
  }
}

// document#3
{
  ...
  "_source": {
    "message": "That is a good name"
  }
}

但是我們的資料一定不會是只有一個欄位,很多個欄位時,ES 怎麼做呢?它會根據欄位來區分 inverted index,我把下圖補上一個 title 就會一目暸然:

那不同的 index 之間有相同的欄位呢?

這個就完全不相關了,就算兩個 index 內都有 message 的欄位,自然而然就會有兩份 inverted index 在不同的 index 中,所以是各自維護和獨立運作的。

我知道有點饒舌,但沒辦法,就是這麼多 index。

結語

下一篇文章,會介紹到 Mapping 這個概念,也會帶入資料的類型一起討論。

記住我們現在討論的 inverted index 都是作用在 text 的資料類型上,可以暫時想像成關聯式資料庫的 string 或是 text,總之其他的資料類型並不是使用 Inverted index 做儲存。


上一篇
Day 17 Elasticsearch - Analyzer 介紹
下一篇
Day 19 Elasticsearch - Mapping 以及基礎資料類型
系列文
30 天學習 Elasticsearch30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言