1. 程式人生 > >ElasticSearch學習總結(三):查詢總結

ElasticSearch學習總結(三):查詢總結

本文主要對Elasticsearch中查詢相關的知識做一個簡單的總結,內容主要包括查詢的評分機制,查詢改寫,過濾器,以及對常見的查詢做一個簡單的分類

1. 評分機制

在Lucense中預設使用TF/IDF演算法對文件進行評分,該演算法已經在前文做了簡單的介紹,這裡主要總結下什麼樣的因素可能得到高分
1. 越罕見的詞被匹配上,得分越高。
2. 文件欄位越短(包含更少的詞項),文件的得分越高
3. 權重越高(可以是索引期或是查詢期賦予的權重),得分越高

Elasticsearch 提供的評分演算法比較豐富(預設為BM25),可以通過similarity進行配置,可配置的專案包括:
1. BM25
2. Classic(基於TF/IDF)
3. DFR/DFI
4. IB
5. ….
關於每個演算法的介紹以及可配置引數可以參見:

https://www.elastic.co/guide/en/elasticsearch/reference/5.2/index-modules-similarity.html

另外需要注意的是除了使用similarity進行評分的控制之外,還可以通過function_score,constant_score,rescore 等多種機制對評分進行更加精確的控制。

2. 查詢改寫

在進行==字首查詢==或是==萬用字元查詢==時,實際上會轉化為對多個關鍵詞的查詢,處於效能優化的考慮,Lucene會把這種查詢轉化為一組開銷較小的查詢方式,採取的主要手段便是“查詢改寫(rewrite)”

查詢改寫使用的主要策略為通過使用常量得分查詢(constant score query)來代替常規查詢來減少查詢時效能的開銷,對於可能匹配term較多的查詢時,效能提升尤為明顯。

在查詢改寫的過程中可以根據需要自定義改寫的方式,可支援的配置如下

  • scoring_boolean:該選項將每個生成的詞項轉化為布林查詢中的一個或從句(Boolean should clause)。這種改寫方法需要針對每個文件都計算得分。因此,這種方法比較耗費CPU,而且有些查詢生成了太多的詞項,以至於超出了布林查詢預設的1024個從句的限制。預設的布林查詢限制可以通過設定Elasticsearch.yml檔案的index.query.bool.max_clause_count屬性來修改。改寫後的布林查詢的從句數越多,查詢效能越低
  • constant_score_boolean:該選項與前面提到過的scoring_boolean類似,但是CPU耗費更少,這是因為並不計算每個從句的得分,而是每個從句得到一個與查詢權重相同的一個常數得分,預設情況下等於1,我們也可以通過設定查詢權重來改變這個預設值。與scoring_boolean類似,該選項也有布林從句數的限制。
  • constant_score(==預設選項==):在匹配的詞項較少時,與constant_score_boolean類似,匹配的詞項較多時,會遍歷並查詢所有的詞項,然後使用相同的常數得分。
  • top_terms_N:與scoring_boolean相似之處在於都會對從句計算得分,不同之處在於,該方法只保留最佳的N個詞項,以避免觸及布林從句數的限制,並提升查詢整體效能。
  • top_terms_boost_N:該選項與top_terms_N類似,不同之處在於它的文件得分不是通過計算得出的,而是被設定為跟查詢權重(boost)一致,預設值為1。

對於如何選擇rewrite配置的問題,可以遵循如下原則
- 如果您能接受較低的精度和相關性(但是追求更高的效能),那麼可以採用top-N查詢改寫方法。
- 如果您需要更高的查詢精度和更好的相關性(同時可以接受較低的效能),那麼應該採用布林方法。

3. 過濾器

3.1 過濾器的作用

Elsaticsearch在提供了豐富查詢功能的同時,還提供了過濾器的功能,過濾器的作用顧名思義,主要用來對查詢結果過濾,但過濾的過程中不會涉及到store的計算效能損耗(是不會對已有查詢的store造成影響),同時頻繁使用的過濾器還會被Elasticsearch自動的快取,總而提高查詢的效能。

3.2 工作原理

過濾器持有的關於文件的唯一重要資訊是該文件是否匹配這個過濾器(僅僅一個標記而已)

過濾器通過返回一個被稱為DocIdSet(org.apache.lucene.search.DocIdSet)的資料結構來提供匹配資訊。這個資料結構的用途是為索引段提供經過濾器過濾後的資料。它可以使用Bits介面(org.apache.lucene.util.Bits)的有關實現。Bits介面可以隨機訪問過濾器中的文件資訊(主要是檢查索引段中的某個文件是否和該過濾器匹配)。

Bits的資料結構非常高效,因為CPU可以使用位運算來完成過濾

下面的表格展示了Bits介面的工作方式

doc bits.get(doc) Result
1 False
2 False
3 True 3
4 True 4

Elasticsearch和Lucene可以根據不同的使用場景選擇不同的DocIdSet實現,不是所有的過濾器都使用Bits結構,比如數值區間過濾器、指令碼過濾器、以及基於地理位置的一組過濾器。這些特殊的過濾器選擇把資料記錄在欄位快取裡,然後再遍歷所需處理的文件集合,逐個進行過濾操作。這意味著過濾器鏈條中的下一個過濾器只能獲取到匹配前一個過濾器的文件集合。因此,可以針對這些過濾器進行優化,比如把最重的(匹配文件最多的,或者效能最差的)過濾器放到過濾器鏈的最後去執行。

4. 查詢的分類

本章節主要總結Elasticsearch支援的常見查詢型別並進行分類,由於Elasticsearch的查詢功能較多,本部分只會選擇性的進行說明,具體使用方法與引數可以參見官方文件:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl.html

4.1 查詢方法

在不使用API的情況下,可以使用兩種方式對資料進行查詢

  • URL查詢
curl -XGET 'localhost:9200/twitter/tweet/_search?q=user:kimchy&pretty'
  • Request Body 查詢
curl -XGET 'localhost:9200/twitter/tweet/_search?pretty' -H 'Content-Type: application/json' -d'
{
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
'

4.2 查詢分類

4.2.1 基本查詢

這類查詢通常作為其他複雜查詢的一部分,或是單獨傳遞給Elasticsearch進行查詢

  • match查詢:該查詢會對==查詢詞==進行分詞,分詞後查詢語句中的任何一個詞項被匹配,文件就會被搜尋到。
  • match_all查詢:該查詢會返回所有的文件。
  • term查詢:該查詢的查詢詞==不會被分詞==。只有文件中的詞和查詢詞精確匹配時才會被搜尋到。
  • query_string查詢:該查詢允許在一個查詢中使用多個特殊的條件關鍵字進行查詢(例如 AND|OR|NOT)對多個欄位進行查詢
  • 其他:match,multi_match,fuzzy_like_this,ids,query_string,simple_query_string,range,prefix,term,terms等等

4.2.2 組合查詢

該種類型的查詢可以嵌入其他查詢以及過濾器
- bool查詢:比較常用的組合查詢,可以把多個查詢用布林邏輯組織在一起。
- dis_max查詢:該種查詢的結果文件得分和最高權重的子查詢打分高度相關,如果希望最高得分的子查詢能夠在打分過程中起決定性的作用,可以使用該類查詢
- 其他:bool,boosting,dis_max,has_child,nested,span-XXX等

4.2.3 無分析查詢

該種類型的輸入不會被分析,而是直接原樣傳遞給lucene

相關查詢主要包括:term,common,ids,prefix,wildcard等等

4.2.4 全文檢索查詢

當需要構建類似於Google這樣的查詢時,可以使用該類查詢,該類查詢會根據輸入與配置進行查詢結果的打分操作。
相關查詢主要包括:match,multi_match,query_string,simple_query_string等

4.2.5 模式匹配查詢

顧名思義,該類查詢主要是用來支援萬用字元查詢的。需要注意的是該類查詢的資源損耗一般都比較大

相關查詢主要包括:prefix,regrex,wildcard

4.2.6 相似度查詢

該類查詢典型的應用場景為近似詞查詢,或是提供類似於Google的”你想找的是不是XXX”的功能

相關查詢主要包括:fuzzy_like_this,fuzzy_like_this_field,more_like_this等

4.2.7 打分相關的查詢

該類查詢可以通過自定義權重的方式來改善查詢精度或是查詢得分。

相關查詢主要包括:boosting,constant_score,function_score,indices

4.2.8 位置敏感查詢

可以使用索引中儲存的詞項位置作為查詢條件的查詢,例如 “需要查詢masting以及elasticsearch兩個詞項,且這連個單詞相互臨近,順序必須是masting在前面,前後距離還不超過3個位置”

該類查詢的開銷也很大,需要消耗大量的CPU資源

相關查詢主要包括:match_phrase,span_XXX

4.2.9 結構敏感查詢

該種類型的查詢可以提供類似於SQL中Join的關係查詢
- nested查詢:文件中可以包含巢狀型別的欄位,這些欄位可以用來索引一些陣列物件,每個物件都可以單獨的查詢,詳細細節可以參考官方文件的nested型別(https://www.elastic.co/guide/en/elasticsearch/reference/5.2/nested.html),以及nested查詢(https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl-nested-query.html)

  • 其他: has_child,has_parent

4.2.10 地理位置查詢

該類查詢主要針對geo_point的查詢以及geo_shape

相關查詢主要包括:geo_distance,geo_bounding_box,geo_polygon,geo_shape

4.2.11 搜尋高亮查詢

該類查詢主要通過對查詢結果使用預設標籤()或是自定義標籤的方式來實現查詢結果高亮的應用場景

相關查詢主要包括:highlighter,fast_vector_highlighter

4.2.12 搜尋排序

Elasticsearch中預設的查詢結果是按照評分排序的,可以使用sort進行排序

4.2.13 其他

  • script查詢:可以使用指令碼進行查詢
  • percolate查詢:該類查詢需要先註冊查詢條件,然後更具文件來查詢條件,常見的使用場景包括:資料分類,資料路由,時間監控等