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 提供的快速跳跃的特性。