ElasticSearch——搜尋機制
在個人的實踐中,ElasticSearch是充當關係型資料庫來使用,將Mysql中資料過大的超過1000w的表存入ES中,所以使用的全部是確切詞查詢而非全文檢索,因此在本次ES的學習中忽略了與全文檢索相關如得分等相關特性,這些在後續的有關搜尋引擎的實踐中會介紹。
在這張腦圖中主要介紹的是搜尋相關的一些機制。下面會對該圖做一些簡單的說明。
簡單查詢
前文說過ES的操作都是基於JSON來控制的,那麼不管是簡單的查詢還是複雜的查詢ES都是通過不同的JSON物件來實現的。
這裡只是簡單的說明,通過腦圖方便記憶,具體的操作可以看 ofollow,noindex">ElasticSearch—— Java API
查詢過程
-
查詢邏輯
- 發散階段:
- 收集階段:
-
搜尋型別
查詢執行的順序,方式等,預設的是query_then_fetch,此方式符合上述的查詢邏輯,現在所有分片上面進行查詢對文件的排序和分級資訊,然後再在相應的分片上面進行查詢實際的文件。
還有一些其他的型別如query_and_fetch,dfs_query_and_fetch,dfs_query_then_fetch等等,可以在搜尋時進行指定:
http://localhost:9200/index/search?pretty=true&search_type=query_and_fetch 複製程式碼
-
搜尋執行的偏好
控制查詢發生在主片還是副本上面,由preference=xxxx指定
http://localhost:9200/index/_search?preference=_primary 複製程式碼
只在主分片上執行搜尋,不使用副本。當想使用索引中最近更新的、還沒複製到副本 中的資訊,這個是很有用的。
基本查詢
ES中的查詢分很多種類,這邊說明幾種常見的使用方式
-
詞條查詢
它僅匹配在給定欄位中含有該詞條的文件,而 且是確切的、未經分析的詞條
{ "query" : { "term" : { "title" : "crime" } } } 複製程式碼
如上上述查詢將匹配title欄位中含有crime一詞的文件。記住,詞條查詢是未經分析的,因此需 要提供跟索引文件中的詞條完全匹配的詞條
而這種方式和傳統SQL中的"="(等值)語句效果一樣。
-
多詞條查詢
詞條查詢允許匹配單個未經分析的詞條,多詞條查詢可以用來匹配多個這樣的詞條。
{ "query" : { "terms" : { "tags" : [ "novel", "book","hello" ], "minimum_match" : 1 } } } 複製程式碼
如上,上述查詢返回在tags欄位中包含一個或兩個搜尋詞條的所有文件。為什麼?這是因為我們 把minimum_match屬性設定為1;這意味著至少有1個詞條應該匹配。如果想要查詢匹配所有詞 條的文件,可以把minimum_match屬性設定為2。
當minimum_match=1時就和SQL中的“in“語句類似了。
-
範圍查詢
範圍查詢使我們能夠找到在某一欄位值在某個範圍裡的文件,欄位可以是數值型,也可以是基於字串的(將對映到一個不同的Apache Lucene查詢),範圍查詢只能針對單個欄位。
{ "query" : { "range" : { "year" : { "gte" : 1700, "lte" : 1900 } } } } 複製程式碼
找到year欄位從1700到1900的所有圖書
類似SQL中的">","<",">=","<="
複合查詢
複合查詢就是支援可以把多個查詢連線起來,或者改變其他查詢的行為。
-
布林查詢
複合查詢就是支援可以把多個查詢連線起來,或者改變其他查詢的行為 主要有如下幾種連線符。
- must :被它封裝的布林查詢必須被匹配,文件才會返回 類似"and"
- should :被它封裝的布林查詢可能被匹配,也可能不被匹配 類似"or"
- must_not:被它封裝的布林查詢必須不被匹配,文件才會返回 類似 "!="
{ "query" : { "bool" : { "must" : { "term" : { "title" : "crime" } }, "should" : { "range" : { "year" : { "from" : 1900, "to" : 2000 } } }, "must_not" : { "term" : { "otitle" : "nothing" } } } } } 複製程式碼
找到所有這樣的文件:在title欄位中含有crime詞條,並且year欄位可以在 也可以不在1900~2000的範圍裡,在otitle欄位中不可以包含nothing詞條。
查詢結果的過濾
過濾器是可以在查詢的結果中做過濾,比如在不影響最後分數的情況下,選擇索引中的某個子集,就可以使用過濾器。
一般來說應該儘可能使用過濾器。 過濾器不影響評分,而得分計算讓搜尋變得複雜,而且需要CPU資源。另一方面,過濾是一種相對簡單的操作 。由於過濾應用在整個索引的內容上,過濾的結果獨立於找到的文件,也獨立於文件之間的關係。 過濾器很容易被快取 ,從而進一步提高過濾查詢的整體效能。
過濾器發生在執行查詢之前,所以效能比較好,應該儘可能的使用過濾器
{ "query": { "filtered" : { "query" : { "match" : { "title" : "Catch-22" } }, "filter" : { "term" : { "year" : 1961 } } } } } 複製程式碼
在title欄位搜尋Catch-22並向其新增過濾器表示只要year=1961的文件。
常見過濾器
- term過濾器
- terms過濾器
- and過濾器
- or過濾器
- bool過濾器 ······
未完待續!!!!!!