1、 什么是DSL查詢
由ES提供豐富且靈活的查詢語言叫做DSL查詢(Query DSL),它允許你構建更加復雜、強大的查詢。
DSL(Domain Specific Language特定領域語言)以JSON請求體的形式出現。
DSL查詢是ES提供的通用查詢方式,這種方式最大的特點是開發語言的無關性,即任意的客戶端只要支持HTTP請求,就可以通過JSON格式的查詢數據完成復雜的搜索。
對於簡單查詢,使用查詢字符串比較好,但是對於復雜查詢,由於條件多,邏輯嵌套復雜,查詢字符串不易組織與表達,且容易出錯,因此推薦復雜查詢通過DSL使用JSON內容格式的請求體代替。
DSL有兩個部分組成:DSL查詢,DSL過濾。
DSL過濾語句和DSL查詢語句非常相似,但是它們的使用目的卻不同:
DSL過濾(精確查找)查詢文檔的方式更像是對於我的條件“有”或者“沒有”,而DSL查詢(模糊查詢)則像是“有多像”。
DSL過濾和DSL查詢在性能上的區別:
過濾結果可以緩存並應用到后續請求。
查詢語句同時匹配文檔,計算相關性,所以更耗時,且不緩存。
過濾語句可有效地配合查詢語句完成文檔過濾。
原則上,使用DSL查詢做全文本搜索或其他需要進行相關性評分的場景,其它全用DSL過濾。
2、 DSL查詢
使用DSL查詢,必須要傳遞query參數給ES。
GET _search
{"query": YOUR_QUERY_HERE}
一個常用的相對完整的DSL查詢:
GET itsource/employee/_search { "query": { "match": {"sex":"女"} }, "_source": ["id","name"], "from": 20, "size": 10, "sort": [{"join_date": "desc"},{"age": "asc"}] }
select id,name from t_user where name like “%heh%” order by id desc limit 0,10.
上面的DSL查詢語句代表:查詢公司員工性別為女的員工,並按照加入時間降序、年齡升序排列,最終返回第21條至30條數據(只返回名字、年齡和email字段)
3、DSL過濾
模糊查詢用DSL的查詢語句,精確查詢用DSL過濾語句。
2.0以上的用法
{ "query": { "bool": { "must": [ {"match": {"description": "search" }} ], "filter": { "term": {"age": "12"} } } }, "_source": ["id","name"], "from": 20, "size": 10, "sort": [{"join_date": "desc"},{"age": "asc"}] }
4、使用DSL查詢與過濾
① 全匹配(match_all)
普通搜索(匹配所有文檔):
{ "query" : { "match_all" : {} } }
如果需要使用過濾條件(在所有文檔中過濾,紅色部分默認可不寫):
{ "query" : { "bool" : { "must" : [{ "match_all":{} }], "filter":{....} } } }
② 標准查詢(match和multi_match)
match查詢是一個標准查詢,不管你需要全文本查詢還是精確查詢基本上都要用到它。
如果你使用match查詢一個全文本字段,它會在真正查詢之前用分析器先分析查詢字符:
{ "query": { "match": { "fullName": "Steven King" } } }
上面的搜索會對Steven King分詞,並找到包含Steven或King的文檔,然后給出排序分值。
如果用 match 下指定了一個確切值,在遇到數字,日期,布爾值或者 not_analyzed的字符串時,它將為你搜索你給定的值,如:
{ "match": { "age": 20 }}
{ "match": { "date": "2016-05-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
multi_match 查詢允許你做 match查詢的基礎上同時搜索多個字段:
{ "query":{ "multi_match": { "query": "Steven King", "fields": [ "fullName","title" ] } } }
上面的搜索同時在fullName和title字段中匹配。
提示:match一般只用於全文字段的匹配與查詢,一般不用於過濾。
③單詞搜索與過濾(Term和Terms)
{ "query": { "bool": { "must": { "match_all": {} }, "filter": { "term": { "age": "20" } } } } }
Terms搜索與過濾
{ "query": { "terms": { "tags": ["jvm", "hadoop", "lucene"], "minimum_match": 2 } } }
minimum_match:至少匹配個數,默認為1
④ 組合條件搜索與過濾(Bool)
組合搜索bool可以組合多個查詢條件為一個查詢對象,查詢條件包括must、should和must_not。
例如:查詢愛好有吃米飯,同時也有喜歡游戲或運動,且出生於1990-06-30及之后的人。Range:范圍
{ "query": { "bool": { "must": [{"term": {"hobby": "吃米飯"}}], "should": [{"term": {"hobby": "游戲"}}, {"term": {"hobby": "運動"}} ], "must_not": [ {"range" :{"birth_date":{"lt": "1990-06-30"}}} ], "filter": [...], "minimum_should_match": 1 } } }
提示: 如果 bool 查詢下沒有must子句,那至少應該有一個should子句。但是 如果有 must子句,那么沒有 should子句也可以進行查詢。
⑤ 范圍查詢與過濾(range)
range過濾允許我們按照指定范圍查找一批數據:
{ "query":{ "range": { "age": { "gte": 20, "lt": 30 } } } }
上例中查詢年齡大於等於20並且小於30。
gt:> gte:>= lt:< lte:<=
⑥ 存在和缺失過濾器(exists和missing)
{ "query": { "bool": { "must": [{ "match_all": {} }], "filter": { "exists": { "field": "gps" } } } } }
提示:exists和missing只能用於過濾結果。
⑦ 前匹配搜索與過濾(prefix)
和term查詢相似,前匹配搜索不是精確匹配,而是類似於SQL中的like ‘key%’
{ "query": { "prefix": { "fullName": "黃" } } }
上例即查詢姓黃的所有人。
⑧ 通配符搜索(wildcard)
使用*代表0~N個,使用?代表1個。
{ "query": { "wildcard": { "fullName": "文*華" } } }