Query DSLhtml
Elasticsearch提供了一個基於JSON的完整的查詢DSL(領域特定語言)。它定義的查詢語言由兩種類型的子句組成:「葉子查詢子句」和「組合查詢子句」。正則表達式
葉子查詢子句json
葉子查詢子句查找特定字段中的特定值,例如 match、term 或 range 查詢。緩存
複合查詢子句app
複合查詢子句包裝其餘葉子或複合查詢,並用於以邏輯方式組合多個查詢(如 bool 或 dis_max 查詢),或更改其行爲(如 constant_score 查詢)。curl
1. Query and filter contextelasticsearch
查詢子句的行爲取決於它是用在查詢上下文(query context)仍是用在過濾器上下文(filter context):ide
1.1. Query context性能
在查詢上下文中的查詢子句回答了「這個文檔與這個查詢子句的匹配程度是怎樣的?」問題。除了決定文檔是否匹配之外,查詢子句還會計算一個「_score」,它表示文檔與其餘文檔的相關程度。ui
1.2. Filter context
在過濾器上下文中,一個查詢子句回答了「這個文檔與查詢子句匹配嗎?」的問題。這個答案是簡單的Yes或者No,也不會計算分數。過濾上下文主要用於過濾結構化數據,例如:
(
PS:Query VS Filter
)
頻繁使用的過濾器將被Elasticsearch自動緩存,以提升性能。
當查詢子句中被傳遞了一個filter參數時過濾器上下文就生效了。例如,bool查詢中的filter參數或者must_not參數。
下面是一個查詢子句的例子,這個查詢將匹配知足如下全部條件的文檔:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "bool": { "must": [ { "match": { "title": "Search" }}, { "match": { "content": "Elasticsearch" }} ], "filter": [ { "term": { "status": "published" }}, { "range": { "publish_date": { "gte": "2015-01-01" }}} ] } } } '
關於上面的查詢子句做以下說明:
(PS:類比SQL的話,match至關於模糊查詢,term至關於精確查詢,range至關於範圍查詢)
2. Match All Query
最簡單的查詢,匹配全部文檔,使它們的_score爲1.0
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} } } '
_score能夠被改變,經過用boost參數
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": { "boost" : 1.2 } } } '
與match_all相反的是match_none,它不匹配任何文檔
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "match_none": {} } } '
3. Full text queries
3.1. Match Query
match查詢接受文本/數值/日期類型的數據,分析它們,並構造一個查詢。
match是一種布爾類型的查詢。這意味着它對提供的文本進行分析,並在分析的過程當中爲提供的文本構造一個布爾查詢。operator 選項能夠設置爲 or 或者 and 以此來控制布爾子句(默認是 or )。例如:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "match" : { "message" : "this is a test" } } } '
注意,查詢語句都是以「query」開頭的,這裏「message」是字段名
你也能夠加一些參數,好比:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "match" : { "message" : { "query" : "this is a test", "operator" : "and" } } } } '
(PS:match是模糊查詢)
3.2. Match Phrase Query
match_phrase 查詢與 match相似,可是它是用於精確匹配或單詞接近匹配的。例如:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "match_phrase" : { "message" : "this is a test" } } } '
固然,你也能夠加參數
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "match_phrase" : { "message" : { "query" : "this is a test", "analyzer" : "my_analyzer" } } } } '
這裏「analyzer」是用來設置用那個分析器來分析文本
3.3. Match Phrase Prefix Query
相似於match_phrase查詢,可是對最後一個單詞進行通配符搜索。
match_phrase_prefix容許文本的最後一個單詞進行前綴匹配
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "match_phrase_prefix" : { "message" : "quick brown f" } } } '
除了match_phrase容許的那些參數外,match_phrase_prefix還能夠接受一個max_expansions參數,它是用來控制最後一個單詞能夠擴展多少後綴(默認50)。
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "match_phrase_prefix" : { "message" : { "query" : "quick brown f", "max_expansions" : 10 } } } } '
3.4. Multi Match Query
multi_match 至關於 match 的多字段版本
顧名思義,multi_match能夠指定多個字段,而match只能針對一個字段
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "multi_match" : { "query": "this is a test", "fields": [ "subject", "message" ] } } } '
另外,字段能夠用通配符,例以下面的例子中能夠查詢 title , first_name , last_name 等字段:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "multi_match" : { "query": "Will Smith", "fields": [ "title", "*_name" ] } } } '
單個字段能夠被提高,例如:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "multi_match" : { "query" : "this is a test", "fields" : [ "subject^3", "message" ] } } } '
上面的例子,subject字段的重要性是message字段的三倍
3.5. Query String Query
支持Lucene查詢字符串語法,容許指定 AND | OR | NOT ,而且在單個查詢字符串中進行多字段查詢
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "query_string" : { "default_field" : "content", "query" : "this AND that OR thus" } } } '
query_string查詢解析輸入並圍繞操做符拆分文本,每一個文本部分都是獨立分析的,例如:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "query_string" : { "default_field" : "content", "query" : "(new york city) OR (big apple)" } } } '
上面的例子中,將被拆分紅 「new york city」 和 「big apple」 兩部分,而且每一部分都被分析器獨立分析
注意,按操做符拆分
query_string的參數包括:
query 實例被解析的查詢文本
default_field 若是沒有指定前綴字段的話,這是默認的查詢字段。(默認查詢全部字段)
default_operator 若是沒有明確指定操做符的話,那麼這是默認的操做符。例如,若是默認操做符是OR的話,那麼「my name is jack」將被翻譯成「my OR name OR is OR jack」,同理,若是是AND,則被翻譯成「my AND name AND is AND jack」
analyzer 用來解析查詢字符串的解析器的名字
allow_leading_wildcard 若是設置了,那麼 * 或 ? 容許做爲第一個字符。默認是true
lenient 若是設置爲true,則格式失敗將被忽略
在query_string中,多字段查詢應該這樣寫:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "query_string" : { "fields" : ["content", "name"], "query" : "this AND that" } } } '
等價於
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "query_string": { "query": "(content:this OR name:this) AND (content:that OR name:that)" } } } '
上面兩個是等價的
3.6. Simple Query String Query
simple_query_string 是query_string的一個更簡單、更健壯、更適合面向用戶的版本
使用SimpleQueryParser解析上下文的查詢。與常規的query_string查詢不一樣,simple_query_string查詢永遠不會拋出異常,並丟棄查詢的無效部分。
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "simple_query_string" : { "query": "\"fried eggs\" +(eggplant | potato) -frittata", "fields": ["title^5", "body"], "default_operator": "and" } } } '
3.7. 實例練習
準備數據
// 刪除索引 curl -X DELETE "192.168.1.134:9200/book" // 建立索引 curl -X PUT "192.168.1.134:9200/book" -H 'Content-Type: application/json' -d' { "settings" : { "number_of_shards" : 1 }, "mappings" : { "_doc" : { "properties" : { "title": { "type": "text" }, "author": { "type": "text" }, "introduction": { "type": "text" }, "publish_date": { "type": "date", "format": "yyyy-MM-dd" } } } } } ' // 查看索引 curl -X GET "192.168.1.134:9200/book?pretty" // 插入文檔 curl -X PUT "192.168.1.134:9200/book/_doc/1" -H 'Content-Type: application/json' -d' { "title" : "Hello Java", "author": "zhangsan", "publish_date" : "2008-11-15", "introduction" : "This is a book for novice." } ' // 查看文檔 curl -X GET "192.168.1.134:9200/book/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} } } '
match查詢(注意,match查詢只能是針對單個字段)
這個例子中,咱們用「Java」查詢到2條,接下來用「Java入門」將查到5條
這是由於解析器會將「Java入門」拆分爲「Java」和「入門」兩個單詞,並且默認的操做符是or
也就是說,查詢的結果是title中包含「Java」或者「入門」的記錄
如今變成查詢title中同時包含「Java」和「入門」的記錄,所以只有1條
multi_match多字段查詢
match_phrase查詢
對比不難發現,一樣的關鍵字「Java從」,用match查出5條,用match_phrase只查出1條
query_string查詢
4. Term level queries(單詞級別查詢)
全文本查詢會在執行以前對查詢字符串進行分析,而單詞級別查詢會對存儲在反向索引中的精確的term進行操做。
這些查詢一般用於結構化的數據,好比:numbers , dates ,enums 等,而不是對全文本字段。
(PS:也就是說,全文本查詢以前要先對文本內容進行分詞,而單詞級別的查詢直接在相應字段的反向索引中精確查找,單詞級別的查詢通常用於數值、日期等類型的字段上)
4.1. Term Query
在指定的字段中查找包含指定的精確的term的文檔
term查詢將在反向索引(或者叫倒排索引)中查找包含特定的精確的term的文檔。例如:
curl -X POST "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "term" : { "user" : "Kimchy" } } } '
上面的例子,在user字段的反向索引中查找包含精確的Kimchy的文檔
還能夠指定一個boost參數,使這個term查詢比另外一個查詢具備更高的相關性得分。例如:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "bool": { "should": [ { "term": { "status": { "value": "urgent", "boost": 2.0 } } }, { "term": { "status": "normal" } } ] } } } '
這個例子中,urgent查詢子句有一個boost參數值爲2.0,這就意味着它的重要程度是後面的normal查詢子句的兩倍,normal子句默認的boost是1.0
4.2. Terms Query
查找包含指定字段中指定的任何確切term的文檔
篩選出與所提供的terms中任何一個匹配的文檔
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "terms" : { "user" : ["kimchy", "elasticsearch"]} } } '
4.3. Range Query
查找指定字段在指定範圍內包含值(日期、數字或字符串)的文檔。
下面的例子返回age字段的值在10到20之間的文檔:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "range" : { "age" : { "gte" : 10, "lte" : 20, "boost" : 2.0 } } } } '
range查詢能夠接受下列參數:
gte 大於或等於
gt 大於
lte 小於或等於
lt 小於
boost 設置boost值,默認是1.0
4.3.1. Range on date fields
當range查詢用於date類型的字段時,範圍能夠用Date Math表示:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "range" : { "date" : { "gte" : "now-1d/d", "lt" : "now/d" } } } } '
當使用Date Math將日期四捨五入到最近的日期、月份、小時等時,四捨五入日期取決於範圍的兩端是包含的仍是排除的。
例如:
rounded up 向上舍入
rounded down 向下舍入
gt 大於2014-11-18||/M 變成 2014-11-30T23:59:59.999
gte 大於或等於2014-11-18||/M 變成 2014-11-01
lt 小於2014-11-18||/M 變成 2014-11-01
lte 小於或等於2014-11-18||/M 變成2014-11-30T23:59:59.999
這個其實很好理解,
大於2014-11-18||/M至關因而大於2014年11月,所以大於2014-11-18||/M等價於大於2014-11-30 23:59:59
也就是說,大於11月,至關因而大於11月的最後一天,即11-30 23:59:59
同理,大於或等於2014-11-18||/M,至關於大於或等於11月,天然是11月的第一天,即2014-11-01
同理,小於2014-11-18||/M,至關於小於11月,天然是小於11月1日,故而小於2014-11-18||/M等價於小於2014-11-01
同理,小於或等於2014-11-18||/M,等於11月天然是包含11月的,意味着小於11月30日,故而小於或等於2014-11-18||/M等價於小於或等於2014-11-30 23:59:59
4.3.2. Date format in range query
在日期範圍查詢的時候,咱們能夠指定日期格式。例如:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "range" : { "born" : { "gte": "01/01/2012", "lte": "2013", "format": "dd/MM/yyyy||yyyy" } } } } '
這個例子是查詢在2012-01-01到2013-12-31之間出生的人
下面看時間範圍查詢
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "range" : { "timestamp" : { "gte": "2015-01-01 00:00:00", "lte": "now", "time_zone": "+01:00" } } } } '
4.4. Exsit Query
在特定的字段中查找非空值的文檔
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "exists" : { "field" : "user" } } } '
4.5. Prefix Query
查找包含帶有指定前綴的term的文檔
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "prefix" : { "user" : "ki" } } } '
能夠關聯boost
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "prefix" : { "user" : { "value" : "ki", "boost" : 2.0 } } } } '
4.6. Wildcard Query
支持通配符查詢,*表示任意字符,?表示任意單個字符
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "wildcard" : { "user" : "ki*y" } } } '
能夠加boost參數
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "wildcard" : { "user" : { "value" : "ki*y", "boost" : 2.0 } } } } '
4.7. Regexp Query
正則表達式查詢
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "regexp":{ "name.first": "s.*y" } } } '
4.8. Ids Query
用_uid字段查詢
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "ids" : { "type" : "_doc", "values" : ["1", "4", "100"] } } } '
4.9. 實例練習
5. 複合查詢
複合查詢包裝其餘複合查詢或葉子查詢,以組合它們的結果和得分,更改它們的行爲,或從查詢切換到篩選上下文。
5.1. 固定分數查詢
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "constant_score" : { "filter" : { "term" : { "user" : "kimchy"} }, "boost" : 1.2 } } } '
5.2. 布爾查詢
關於should子句,特別要注意:
若是這個布爾查詢位於查詢上下文,而且有must或者filter子句,那麼即便should子句沒有匹配任何文檔,也不要緊
若是是位於過濾器上下文,或者既沒有must也沒有filter,那麼至少有一個should查詢必須匹配文檔。
這個行爲能夠經過設置minimum_should_match參數來顯式地控制。
舉個例子:
curl -X POST "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "bool" : { "must" : { "term" : { "user" : "kimchy" } }, "filter": { "term" : { "tag" : "tech" } }, "must_not" : { "range" : { "age" : { "gte" : 10, "lte" : 20 } } }, "should" : [ { "term" : { "tag" : "wow" } }, { "term" : { "tag" : "elasticsearch" } } ], "minimum_should_match" : 1, "boost" : 1.0 } } } '
查詢user爲「kimchy」,而且tag爲「tech」,而且age不在10~20之間,而且tag爲wow或elasticsearch的文檔
filter查詢分數默認是0
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d' { "query": { "bool": { "filter": { "term": { "status": "active" } } } } } '
5.3. 實例練習
參考
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html