《深入理解Elasticsearch(原書第2版)》一2.5.1 查詢方式分類
本節書摘來華章計算機《深入理解Elasticsearch(原書第2版)》一書中的第2章 ,第2.5.1節,[美]拉斐爾·酷奇(Rafal Ku) 馬雷克·羅戈任斯基(Marek Rogoziski)著 張世武 餘洪淼 商旦 譯 更多章節內容可以訪問雲棲社區“華章計算機”公眾號查看。
2.5.1 查詢方式分類
當然,對查詢方式進行分類是一件艱難的任務,我們也不敢打包票說在這裏給出的分類列表是唯一正確的。我們甚至可以說,如果你詢問其他Elasticsearch使用者,他們可能會給出自己的分類方式,或者聲稱每個查詢方式都可以被歸入多個類別。有趣的是,他們有可能是對的。我們也曾考慮過多種分類方式存在的情況,不過,最終我們認為,每個查詢方式都可以被歸入以下列出的一個或多個類別中。
- 基本查詢:這類查詢允許針對索引的一部分進行檢索,其輸入數據既可以分析也可以不做分析。這類查詢的一個關鍵特征是,不支持在其內部再嵌套其他查詢。基本查詢的一個示例是term查詢。
- 組合查詢:在這類查詢中可以包含其他查詢和過濾器,比如bool查詢和dismax查詢。
- 無分析查詢:這類查詢不分析輸入內容,直接將它們原樣傳遞給Lucene。term查詢就是這類查詢的一員。
- 全文檢索查詢:這類查詢成員眾多。許多查詢都支持全文檢索、輸入內容分析、同時很可能支持可被Lucene識別的查詢語法。比如match查詢。
- 模式匹配查詢:這類查詢都在查詢語句中支持各種通配符。比如,前綴查詢可以歸入此類。
- 支持相似度操作的查詢:這類查詢擁有一個共同的特性—支持近似詞語的匹配。這類查詢的成員如fuzzy_like_this、more_like_this查詢等。
- 支持打分操作的查詢:這類查詢非常重要,尤其是在和全文搜索查詢組合使用的場景下。這個類別包括那些允許在查詢時修改打分計算過程的查詢方式。在第3章介紹的function_score查詢可以歸入此類。
- 位置敏感查詢:這類查詢允許我們使用索引中存儲的詞項位置信息。span_term查詢就是一個很好的例子。
結構敏感查詢:這類查詢的工作基於結構數據,如父子文檔結構。這個類別的一個例子是nested one查詢。
當然,我們在這裏隻討論查詢分類,不探討過濾器的分類。不過,對過濾器來說,你也可以使用相同的分類邏輯。讓我們先把過濾器置之腦後。在距離闡釋每種查詢類別之前,我們先簡短描述一下每種查詢類別的目的。
1. 基本查詢
在基本查詢內部不可以包含其他查詢,它們隻有索引檢索這一個用途。這類查詢通常作為其他複雜查詢的一部分或者單獨傳遞給Elasticsearch。你可以把基本查詢比作修築大廈的磚塊,而大廈就是各種複雜查詢。舉個例子,如果你想匹配某個文檔中的一個特定詞項,且沒有其他要求,可以考慮使用基本查詢。本例中,match查詢就能很好地滿足需求,無需再跟其他查詢組合使用。
歸屬於基本查詢的一些查詢方式舉例如下:
- match查詢:一種(實際上指好幾種)查詢方式,適用於執行全文檢索且需要對輸入進行分析的場景。一般來說,當需要分析輸入內容卻不需要完整Lucene查詢語法支持時,可以使用這種查詢方式。這種查詢不需要進行查詢語法解析,發生解析錯誤的概率極低,因此特別適合接收用戶輸入文本的場景。
- match_all查詢:這個查詢匹配所有文檔,常用於需要對所有索引內容進行歸類處理的場景。
- term查詢:一種簡單的、無需對輸入進行分析的查詢方式,可以查詢單個詞語。這種查詢方式的使用場景包括針對不分詞字段進行檢索,比如在我們的測試代碼中檢索tags字段。term查詢還經常跟過濾器配合使用,比如在我們的測試代碼中針對category字段進行過濾操作。 簡單查詢分類可包括:match,multi_match,common,fuzzy_like_this,fuzzy_like_this_field,geoshape,ids,match_all,query_string,simple_query_string,range,prefix, regexp,span_term,term,terms,wildcard查詢。
** 2. 組合查詢**
組合查詢的唯一用途是把其他查詢組合在一起使用。如果說簡單查詢是建造高樓的磚塊,組合查詢就是粘合這些磚塊的水泥。我們可以把組合查詢無窮嵌套,用來構建極其複雜的查詢,唯一能夠阻止我們這樣嵌套的障礙是性能。
組合查詢的一些示例和用法如下。
bool查詢:最常用的組合查詢方式之一。能夠把多個查詢用布爾邏輯組織在一起,可以控製查詢的某個子查詢部分是必須匹配、可以匹配還是不應該匹配。如果我們要把匹配不同查詢條件的查詢組合在一起使用,bool查詢就是一個很好的選擇。Bool查詢還可以用在這樣的場景:我們希望結果文檔的最終得分為所有子查詢得分的和。
dis_max查詢:一種非常有用的查詢方式。這種查詢的結果文檔得分和最高權重的子查詢打分高度相關,而不是如bool查詢那樣對所有子查詢得分進行求和。Dis_max查詢返回匹配所有子查詢的文檔,並通過一個簡單公式計算最終得分:max(各子查詢的得分)+tie_breaker*(非最高得分子查詢的得分之和)。如果你希望最高得分子查詢能夠在打分過程中起決定作用,dis_max查詢是不二選擇。
組合查詢類別可包括這些查詢方式:bool,boosting,constant_score,dis_max,filtered,function_score,has_child,has_parent,indices,nested,span_first,span_multi, span_first,span_multi,span_near,span_not,span_or,span_term,top_children查詢。
3. 無分析查詢
有一類查詢不會被分析,而是直接傳遞給Lucene索引。這意味著我們既不需要操心分析過程是否如我們期望的方式執行並生成合適的詞項,也不需要針對特定的不分詞字段執行查詢。如果你把Elasticsearch當作NoSQL數據庫使用,這種查詢方式就比較適合你。這類查詢精確匹配傳入的詞語,不會使用語言分析器等工具對詞語進行分詞和其他處理。
以下示例可幫你理解無分析查詢的目的。
- term查詢:即詞項查詢。當提及無分析查詢時,最常用的無分析查詢就是term查詢。它可以匹配某個字段中的給定值。比如說,如果你希望匹配一個擁有特定標簽(我們示例文檔中的tags字段)的文檔,可以使用term查詢。
- prefix查詢:即前綴查詢。另一種無需分析的查詢方式。前綴查詢常用於自動完成功能,用戶輸入一段文本,搜索係統返回所有以這個文本開頭的文檔。需要注意的是,盡管前綴查詢沒有被分析,Elasticsearch還是對它進行了重寫,以確保它能高速執行。 這類查詢包括:common,ids,prefix,span_term,term,terms,wildcard查詢。
4. 全文檢索查詢
當你需要構建類似Google的查詢界麵時,可以使用這種查詢類別。這類查詢會根據索引映射配置對輸入進行分析,支持Lucene語法和打分計算等功能。一般來說,如果查詢的一部分文本來自於用戶輸入,則可以從全文檢索查詢類別中選擇其一,比如query_string、match或simpe_query_string查詢。
全文檢索查詢類別的示例和用法如下。
- simle_query_string查詢:該查詢方式構建於Lucene的SimpleQueryParser類(參考https://lucene.apache.org/core/4_9_0/queryparser/org/apache/lucene/queryparser/simple/SimpleQueryParser.html,被設計為解析人類可讀的查詢串)之上。通常情況下,如果你不希望在遭遇解析錯誤時直接失敗,而是嚐試給出用戶期望的答案,那麼這種查詢方式是不錯的選擇。
屬於本類的查詢方式包括:match,multi_match,query_string,simple_query_string查詢。
5. 模式匹配查詢
Elasticsearch直接或間接提供了一些支持通配符的查詢方式,比如通配符查詢(wildcard query)和前綴查詢(prefix query)。除此之外,我們還可以使用正則表達式查詢(regexp query),這種查詢能夠找出內容中包含給定模式的文檔。
我們在之前已經展示過一個前綴查詢的示例,因此在這裏主要介紹一下正則表達式查詢。如果想找出其詞項匹配某個固定模式的文檔,正則表達式查詢是唯一的選擇。舉個例子,假定你的各種日誌存儲於Elasticsearch中,可以使用正則表達式查詢找出所有含有如下詞項的日誌記錄:詞項以“err”前綴開頭、以“memory”結尾、中間可以有任意數量的字符。最後,需要注意的是,所有模式匹配查詢如果包含可匹配海量詞項的表達式,性能代價將十分高昂。
本類查詢包括:prefix,regexp,wildcard查詢。
6. 支持相似度操作的查詢
我們認為這類查詢是一些可以根據給定詞項查找近似詞項或文檔的查詢方式的集合。舉例來說,假定我們需要找出包含“crimea”近似詞項的文檔,可以執行一個fuzzy查詢。這類查詢的另一個用途是提供類似“你是不是想找XXX”的功能。比如你希望找出文檔標題和輸入文本相似的文檔,可以使用more_like_this查詢。一般來說,你可以使用本類別下的某個查詢來查找包含和給定輸入近似詞項或字段的文檔。
屬於這個類別的查詢有:fuzzy_like_this,fuzzy_like_this_field,fuzzy,more_like_this,more_like_this_field查詢。
7. 支持打分操作的查詢
這是一組用於改善查詢精度和相關度的查詢方式。這類查詢可以通過指定自定義權重因子或提供額外處理邏輯的方式來改變文檔得分。這類查詢的一個很好的例子是function_score查詢。function_score查詢可以讓我們使用函數,從而通過數學計算的方式改變文檔得分。舉個例子,如果你希望離給定地理定位點越近的文檔得分越高,則function_score查詢可以幫助實現這個目的。
本類查詢包括:boosting,constant_score,function_score,indices查詢。
8. 位置敏感查詢
這類查詢不僅可以匹配特定詞項,還能匹配詞項的位置信息。Elasticsearch提供的各種範圍查詢就是這類查詢的典型代表。我們還可以把match_phrase查詢歸入本類,因為至少從某種程度上來說,它也需要考慮被索引詞項的位置信息。如果需要找出一組和其他單詞保持一定距離的單詞,比如“找出以下文檔,同時包含mastering和Elasticsearch且這兩個單詞相互臨近,其後不超過距離3的位置包含second和edition單詞”,可以使用各種範圍查詢。不過,需要注意的是,這些範圍查詢將在未來版本的Lucene庫中將被移除,屆時Elasticsearch也不再提供支持。這是因為這些查詢開銷很大,需要消耗大量CPU資源才能保證正確處理。
本類查詢包括:match_phrase,span_first,span_multi,span_near,span_not,span_or,span_term查詢。
9. 結構敏感查詢
最後一類查詢是結構敏感查詢(structure aware query)。這類查詢包括:
- nested查詢
- has_child查詢
- has_parent查詢
- top_children查詢
一般來說,所有支持對文檔結構進行檢索並且不需要對文檔數據進行扁平化處理的查詢方式都可以歸入此類。如果你正在尋找一種查詢方式,能夠在子文檔或嵌套文檔中進行查詢,或查找屬於給定父文檔的子文檔,則需要使用剛剛提及的查詢方式之一。換句話說,如果需要處理文檔中的數據關係,請選擇使用這類查詢。不過需要注意的是,盡管Elasticsearch可以支持一些數據關係,但它畢竟不是真正的關係數據庫。
最後更新:2017-06-23 23:03:01