elasticsearch(5) 請求體搜尋
上一篇提到的輕量搜尋非常簡單便捷,但是通過請求體查詢可以更充分的利用查詢的強大功能。因為_search api中大部分引數是通過HTTP請求體而非查詢字串來傳遞的。
一 空查詢
對於空查詢來說,最簡單的方式就是傳入一個空的請求體,獲取所有文件(預設返回前10個完整文件內容)
GET 127.0.0.1:9200/_search {}
你也可以使用from 和 size引數
GET 127.0.0.1:9200/_search { "from":10, "size":5 }
這樣的方式來查詢第11條到15條的文件
- 大家可能會好奇,這明明是一個GET請求方式,為何可以有請求體。事實上這個RFC文件
GET
請求應該如何處理。結果是,一些 HTTP 伺服器允許這樣子,而有一些 — 特別是一些用於快取和代理的伺服器則不允許。
為了避免這樣的情況,ES也支援通過POST請求來進行查詢
POST 127.0.0.1:9200/_search { "from":10, "size":5 }
二 查詢結構
查詢表示式(Query DSL)是一種非常靈活又富有表現力的 查詢語言。 Elasticsearch 使用它可以以簡單的 JSON 介面來展現 Lucene 功能的絕大部分。在你的應用中,你應該用它來編寫你的查詢語句。它可以使你的查詢語句更靈活、更精確、易讀和易除錯。
要使用查詢表示式只需要將查詢語句傳遞給query引數
- 典型的查詢語句結構
{
QUERY_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
例如
{ "query": { "match": { "like": "sport" } } }
查詢like欄位包含sport的文件
- 合併查詢語句
查詢語句就行一個組合塊,這些組合塊可以合併組成更加複雜的查詢邏輯
合併查詢語句裡分為兩種型別
1、葉子語句
即類似上述的match語句,可以被用來查詢一個或多個欄位的文件
2、複合語句
用於合併其他查詢語句,可以通過一個bool語句組合其他語句,例如must匹配、must_not匹配,should匹配,或者filters過濾器
示例
{ "bool": { "must": { "match": { "email": "business opportunity" }}, "should": [ { "match": { "starred": true }}, { "bool": { "must": { "match": { "folder": "inbox" }}, "must_not": { "match": { "spam": true }} }} ], "minimum_should_match": 1 } }
找出信件正文包含 business opportunity
的星標郵件,或者在收件箱正文包含business opportunity
的非垃圾郵件
三 查詢與過濾
查詢元件的使用可以分為兩種情況,查詢情況和過濾情況,這兩種情況是有區別的
- 對於過濾情況來說,ES只是簡單的過濾查詢,對於文件是不會進行評分的,即文件要麼匹配,要麼就是不匹配,並沒有介於其中的中間狀態。
這種方式比較適用於確定的判斷,例如created介於2017和2018之間,status等於有效等等
- 對於查詢情況來說,查詢就有了評分,不但需要判斷文件是否匹配,還需要判斷這個文件匹配的多好。
這種情況比較適用於全文搜尋,因為全文搜尋幾乎沒有完全正確的答案
一般情況下,由於查詢情況需要評分,所以它的效率是沒有過濾情況來的好的。通常使用 查詢(query)語句來進行全文 搜尋或者其它任何需要影響相關性得分的搜尋。除此以外的情況都使用過濾(filters)。
- 實際上從ES2.0開始,過濾情況已經基本被排除了,因為查詢擁有了不評分的能力。
四 查詢方法
- match_all
match_all查詢簡單的匹配所有文件,在沒有指定查詢方式時,它是預設的查詢,它經常與 filter 結合使用。由於所有文件被認為具有相同的相關性,所以文件的_score都為1
{ "query": { "match_all": {} } }
- match
無論你在任何欄位上進行的是全文搜尋還是精確查詢,match
查詢是你可用的標準查詢。如果是在全文欄位上match,那麼就會使用正確的分析器取分析查詢字串,如果是在精確值例如整型,時間等,那麼就會精確匹配它。這部分內容會在後面的對映分析部分講到。
{ "query": { "match": { "like": "sport" } } }
- multi_match
multi_match查詢可以在多個欄位上執行相同的match, query屬性裡是查詢的條件,fields屬性對應的是多個欄位。
{ "query": { "multi_match": { "query": "sport", "fields":["like","career"] } } }
- range查詢
range查詢可以找出落在指定區間內的數字或者時間,被允許的操作符有
gt:大於
gte:大於等於
lt:小於
lte:小於等於
{ "query": { "range": { "age": { "gte": 20, "lt": 30 } } } }
- term查詢
term查詢用於精確值匹配,這些精確值可能是數字、時間、布林或者那些未被分析的字串
{ "term": { "age": 26 }}
- terms查詢
和term一樣,但terms允許指定多值進行匹配,若包含任一值,文件則匹配。匹配的多值通過[ ] 來列出
{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
- exists查詢
查詢指定欄位有值,NOT NULL。field:指定欄位
{ "exists": { "field": "title" } }
- missing查詢
和exists相反,查詢指定欄位無值 NULL.
五 組合多查詢
可以通過bool查詢來合併組合多查詢,bool查詢接受一下引數
- must
文件必須匹配這些條件才能被包含
- must_not
文件必須不匹配這些條件才能被包含
- should
如果滿足這些語句中的任意語句,將會增加_score,否則無任何影響,它主要用於修正每個文件的相關性得分
- filter
必須匹配,但它以不評分、過濾模式來進行。這些語句對評分沒有貢獻,只是根據過濾標準來排除或包含文件。所有查詢包括bool查詢本身都可以放置在filter語句中,使其本身不做評分。
- 如果沒有must語句,那麼至少需要能夠匹配其中的一條
should
語句。但,如果存在至少一條must
語句,則對should
語句的匹配沒有要求。
六 驗證查詢
可以使用_validate/query來驗證查詢是否合法
GET /test/test/_validate/query { "query": { "like" : { "match" : "sport" } } }
響應
{ "valid" : false, "_shards" : { "total" : 10, "successful" : 10, "failed" : 0 } }
這告訴我們這是非法的查詢,這時我們可以使用explain來查詢原因
GET /gb/tweet/_validate/query?explain { "query": { "tweet" : { "match" : "really powerful" } } }
響應
{ "valid" : false, "_shards" : { ... }, "explanations" : [ { "index" : "gb", "valid" : false, "error" : "org.elasticsearch.index.query.QueryParsingException: [gb] No query registered for [tweet]" } ] }
這告訴我們query中沒有註冊的tweet,應該把match和tweet調換位置