天天看點

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

本節書摘來華章計算機《深入了解elasticsearch(原書第2版)》一書中的第2章 ,第2.5.2節,[美]拉斐爾·酷奇(rafal ku) 馬雷克·羅戈任斯基(marek rogoziski)著 張世武 餘洪淼 商旦 譯 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

既然我們已經了解了各類查詢方式的适用場合以及期望結果,現在可以趁熱打鐵,用具體的使用示例來進一步加強對它們的認知。注意,這些例子并不能覆寫elasticsearch查詢的方方面面,而僅僅是對于我們通過查詢擷取所需資訊的一些簡單示例說明。

1. 測試資料

為了達到本節的目的,我們給library索引加入了兩個新文檔。

首先,我們需要微調一下索引映射以支援嵌套文檔(本節某些例子中需要用到)。修改映射的指令如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

然後,接着索引兩個新文檔。相關指令如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

2. 基本查詢示例

讓我們看一下使用基本查詢類别的例子。

(1)查詢給定範圍的資料

比對給定取值範圍的文檔的查詢是最簡單的查詢方式之一。通常,這種查詢作為一個更複雜查詢或過濾器的一部分而存在。舉例來說,一個可以查出副本數在[1,3]區間的書籍的查詢如下所示:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

(2)簡化的多詞項查詢

想象一個場景,使用者需要傳入一組書籍标簽,期望查詢出比對這些标簽的書籍。還有一個條件,如果使用者給出的标簽超過3個,則隻要求至少75%的給定标簽與索引中的書籍比對。通常我們可以通過bool查詢去實作這個目的,不過elasticsearch提供了可以實作相同目的的terms查詢。執行查詢的指令如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

3. 組合查詢示例

現在我們看看如何使用組合查詢來組合其他查詢方式。

(1)對比對文檔權重

最簡單的示例是使用包含一個可選的權重片段的bool查詢來實作對部分文檔的權重提升。舉例來說,如果需要找出所有至少擁有一個副本的書籍,并對1950年後出版的書籍進行權重,可以使用如下查詢指令:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

(2)忽略查詢的較低得分部分

我們之前提到的dis_max查詢可以控制查詢中較低得分部分的影響。舉例來說,如果我們期望找出所有title字段比對“crime punishment”或characters字段比對“raskolnikov”的文檔,并在文檔打分時僅考慮得分最高的查詢片段,可以執行如下查詢指令:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

查詢結果如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

我們來單獨看一下查詢各部分的打分。可以單獨執行如下查詢片段:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

單獨執行下一個查詢片段的指令如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

可以看出,dis_max查詢傳回的文檔得分等于打分最高的查詢片段的得分(上面的第一個查詢片段)。這是因為我們設定tie_breaker屬性為0.0。

4. 無分析查詢示例

讓我們看看兩個不使用任何分析器的查詢示例。

(1)找出符合标簽的結果

elasticsearch提供的term查詢是最簡單的無分析查詢之一。我們一般很少單獨使用term查詢,而是常常将其使用在各種複合查詢中。舉個例子,假設我們想要查找出所有tags字段包含“novel”值的書籍。為了達到這個目的,需要執行如下查詢指令:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

(2)在查詢時高效處理停用詞

elasticsearch提供了普通的terms查詢,可以在查詢時用一種高效的方式處理停用詞。它将查詢詞項分成兩組—重要的詞項和不重要詞項。重要詞項的出現頻率較低,相反,不重要詞項的出現頻率很高。elasticsearch首先用重要詞項執行查詢并計算文檔得分,然後再使用不重要詞項執行查詢,這時不再計算文檔得分。是以查詢可以變得更快。

舉例來說,以下兩個查詢單就查詢結果而言非常相似,而結果的打分卻不一樣。注意,如果想清楚地看出兩者打分的不同,我們需要準備大量的資料樣本,并在索引時禁用停用詞。

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

第二個查詢如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

5. 全文檢索查詢示例

全文檢索是一個寬泛的主題,其使用場景也十分廣泛。在這裡我們選出兩個簡單場景的查詢示例加以展示。

(1)使用lucene查詢文法

某些時候,使用lucene查詢文法是不錯的選擇。我們曾在1.1.4節介紹過lucene查詢文法。舉個例子,假如我們想找出title字段包含“sorrows”和“young”詞項、author字段包含“von goethe”短語,并且副本數不超過5個的文檔,可以執行如下查詢:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

在這個查詢中,我們使用了lucene查詢文法來傳遞所有比對條件,讓lucene通過查詢解析器來構造合适的查詢。

(2)對使用者查詢串進行容錯處理

在某些場景下,來自使用者的查詢可能包含錯誤。比如,下面這個查詢:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

elasticsearch将傳回如下響應:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

這意味着在建構查詢時遇到了解析錯誤,查詢無法被成功地建構出來。這也是elasticsearch引入simple_query_string查詢的原因。它使用一個可嘗試處理使用者輸入錯誤的查詢解析器,并試圖猜測使用者的查詢用意。如果用simple_query_string查詢來改寫上面這個例子,代碼如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

如果執行這個查詢,你将看到elasticsearch能夠傳回合适的文檔結果,盡管查詢并未被恰當構造。

6. 模式比對查詢示例

模式比對查詢的例子很多,不過在這裡我們隻打算展示其中兩個。

(1)使用字首查詢實作自動完成功能

針對索引資料提供自動完成功能是一種常見的應用場景。如我們所知,字首查詢不會被分析,直接工作于特定字段中被索引的詞項上。是以,實際的功能依賴于索引時生成詞條的方式。舉例來說,假定我們希望針對title字段的所有詞條提供自動完成功能。此時使用者輸入的字首是“wes”,符合條件的對應查詢構造如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

(2)模式比對

如果我們想比對特定模式,而此時索引中的詞條無法支援,可以嘗試使用regexp查詢。讀者需要注意的是,這種查詢非常昂貴,請盡量避免使用。當然,有時候我們不得不使用它。還有一點需要注意的是,regexp查詢的執行性能與所選正規表達式相關。如果你選擇了一個能夠被改寫成大量詞項的正規表達式,執行性能将極其糟糕。

現在我們來看一下使用regexp查詢的例子。假定我們需要找出符合以下條件的文檔:文檔的characters字段中包含以“wat”開頭、以“n”結尾、中間有兩個任意字元的詞項。為了實作這些條件,可以使用類似下面的regexp查詢指令:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

7. 支援相似度操作的查詢示例

讓我們看兩個關于如何查找近似文檔和詞項的簡單示例。

(1)找出給定詞項的近似詞項

一個非常簡單的例子是使用fuzzy查詢找出包含給定詞項近似詞項的文檔。比如,如果我們需要查找包含“crimea”的近似詞項的文檔,可以執行如下查詢指令:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

(2)找出擁有近似字段值的文檔

另一個相似度查詢的案例是,根據我們在查詢中提供的字段值,找出包含類似字段值的文檔。比如,我們想找出title字段值類似“western front battles”的書籍,可以構造如下查詢:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

從上面結果可見,有時候查詢結果跟我們的期望有些出入(比如結果中第2本書的标題)。這是因為elasticsearch認為它們之間有相似性。在前面這個查詢中,elasticsearch将對所有詞項執行一次模糊查詢,然後為比對的文檔選擇出一組最佳查分詞項。

8. 支援打分操作的查詢示例

涉及相關度,elasticsearch提供了一些可以按需修改文檔得分的查詢。當然,大多數查詢方式都支援權重,可以讓我們擁有更多的操作餘地。接下來讓我們看看兩個支援打分操作的查詢示例。

(1)偏愛新書

假定我們更喜歡新出版的書籍,是以1986年出版的書籍要比1870年出版的書籍擁有更高的得分。滿足這個需求的查詢指令如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

我們将在第3章介紹function_score查詢。在這裡,如果你仔細觀察剛才這個查詢的響應結果,可以發現越新的書籍得分越高。

(2)對擁有某些值的書籍扣分

有時候,我們需要降低某些文檔的重要性,卻依然要在結果清單中輸出它們。舉個例子,我們可能想要列出所有的書籍,不過要通過降低書籍得分的方式把那些目前無貨的書籍放到結果清單的末尾。我們不希望按标記是否有貨的字段進行排序,因為使用者有時候清楚地知道他要找什麼書,是以針對全文檢索查詢的結果得分是很重要的。不過,如果僅僅想把目前無貨的書籍排到結果尾部,可以執行如下查詢指令:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

9. 位置敏感查詢示例

位置敏感查詢允許我們比對包含正确次序短語和詞項的文檔。這類查詢因為資源占用問題,不經常被使用。讓我們看兩個例子。

(1)比對短語

比對短語的match_phrase查詢是最簡單的位置敏感查詢,也是本類别中使用最多的。舉例來說,otitle字段比對短語“leiden des jungen”的查詢指令如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

(2)處處可見範圍查詢

當然,短語查詢在處理位置敏感需求時非常簡便。不過,如果我們想執行一個查詢,找出符合以下條件的文檔:在“die”詞項後面不超過兩個位置的地方包含一個“des jungen”短語,并且緊跟着短語後面是一個“werthers”詞項。這時候,該怎麼辦呢?我們可以使用範圍查詢。符合這些條件的查詢指令類似如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例
《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

注意,範圍查詢是不經過分析器處理的。我們可以通過檢視explain api的響應來确認這一點。為了看到explain api的響應,我們需要把剛才這個查詢指令的請求體(或者叫查詢内容)發送到/library/book/5/_explain這個rest端點。響應的有趣部分如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

10. 結構敏感查詢示例

如果涉及嵌套文檔或父子文檔關系,遲早會用到結構敏感查詢。讓我們從下面兩個例子中看一下這類查詢是如何使用的。

(1)傳回包含某個嵌套子文檔的父文檔

第一個例子非常簡單。假定我們要查找所有擁有4星及以上評論的書籍。相應的查詢指令如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

(2)嵌套子文檔的得分影響父文檔得分

假定我們要傳回所有擁有評論的書籍,并且按照最高評論星級對這些書籍進行排序。滿足這些條件的查詢指令如下:

《深入了解Elasticsearch(原書第2版)》一2.5.2 使用示例

繼續閱讀