Elasticsearch的Term為什麼很快之跳錶

  • 2020 年 3 月 31 日
  • 筆記

term代表完全匹配,也就是精確查詢,搜索前不會再對搜索詞進行分詞,所以我們的搜索詞必須是文檔分詞集合中的一個,此欄位如 "無分詞",則完全匹配此欄位(如果對於某個欄位,你想精確匹配,即搜索什麼詞匹配什麼詞,類似sql中的=操作,則應該採取此操作),下面是用的kibana的示例數據的Term操作。

GET kibana_sample_data_ecommerce/_search  {    "query": {      "bool": {        "must": [{            "term": {              "customer_first_name.keyword": {                "value": "Mary"              }            }          },          {            "term": {              "customer_gender": {                "value": "FEMALE"              }            }          }        ]      }    }  }

假設我們有以下數據:

docId

customer_first_name

customer_gender

1

Marry

FEMALE

2‍‍‍

Shen

MALE

3

Marry

FEMALE

這裡每一行是一個document。每個document都有一個docid。那麼給這些document建立的倒排索引就是:

customer_first_name

Marry

[1,3]

Shen

[2]

customer_gender

FEMALE

[1,3]

MALE

[2]

可以看到,倒排索引是按欄位的,一個欄位有一個自己的倒排索引。Marry,Shen這些叫做 term,而[1,3]就是posting list。Posting list就是一個int的數組,存儲了所有符合某個term的文檔id。

利用 Skip List 合併

以上是三個posting list。我們現在需要把它們用AND的關係合併,得出posting list的交集。首先選擇最短的posting list,然後從小到大遍歷。遍歷的過程可以跳過一些元素,比如我們遍歷到綠色的13的時候,就可以跳過藍色的3了,因為3比13要小。

整個過程如下

Next -> 2  Advance(2) -> 13  Advance(13) -> 13  Already on 13  Advance(13) -> 13 MATCH!!!  Next -> 17  Advance(17) -> 22  Advance(22) -> 98  Advance(98) -> 98  Advance(98) -> 98 MATCH!!!

最後得出的交集是[13,98],所需的時間比完整遍歷三個posting list要快得多。但是前提是每個list需要指出Advance這個操作。Advance操作是什麼?就是 skip list 提供的快速跳躍的特性。