[TOC]
一刷允、DSL
在 ElasticSearch 中,提供了功能十分豐富碧囊、多種表現(xiàn)形式的查詢語(yǔ)言—— DSL 查詢恃锉。
Query DSL 又叫結(jié)構(gòu)化查詢,使用 JSON 格式的請(qǐng)求體 與 ElasticSearch 交互呕臂,使查詢語(yǔ)句更靈活、更精確肪跋、更易讀且易調(diào)試歧蒋。
使用結(jié)構(gòu)化查詢,你需要傳遞 query
參數(shù):
GET /_search
{
"query": YOUR_QUERY_HERE
}
主要包含兩種類型的查詢語(yǔ)句:葉子查詢語(yǔ)句和復(fù)合查詢語(yǔ)句州既。
1.1谜洽、葉子查詢語(yǔ)句
這種查詢可以單獨(dú)使用,針對(duì)指定的字段查詢指定的值吴叶,例如:match, term, range 等阐虚。
一個(gè)葉子查詢語(yǔ)句一般使用這種結(jié)構(gòu):
{
QUERY_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
或指向一個(gè)指定的字段:
{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
例如,可以使用 match
查詢子句用來(lái)找尋在 tweet
字段中找尋包含 elasticsearch
的成員:
GET /_search
{
"query": {
"match": {
"tweet": "elasticsearch"
}
}
}
1.2蚌卤、復(fù)合查詢語(yǔ)句
這種查詢可以合并其他的葉子查詢或復(fù)合查詢实束,從而實(shí)現(xiàn)非常復(fù)雜的查詢邏輯。
例如逊彭,bool
子句允許合并其他的合法子句咸灿,must
,must_not
或者 should
:
{
"bool": {
"must": { "match": { "tweet": "elasticsearch" }},
"must_not": { "match": { "name": "mary" }},
"should": { "match": { "tweet": "full text" }}
}
}
二侮叮、Query DSL 和 Filter DSL
Elasticsearch 使用的查詢語(yǔ)言(DSL) 擁有一套查詢組件避矢,這些組件可以以無(wú)限組合的方式進(jìn)行搭配。這套組件可以在以下兩種情況下使用:查詢情況 query context
和過(guò)濾情況 filtering context
囊榜,也即結(jié)構(gòu)化查詢 Query DSL
和結(jié)構(gòu)化過(guò)濾 Filter DSL
审胸。
查詢與過(guò)濾語(yǔ)句非常相似扔字,但是它們由于使用目的不同而稍有差異蛉威。
2.1、Query DSL
在上下文查詢語(yǔ)境中卑吭,查詢語(yǔ)句會(huì)詢問(wèn)文檔與查詢語(yǔ)句的匹配程度豆赏,它會(huì)判斷文檔是否匹配并計(jì)算相關(guān)性評(píng)分(_score)的值掷邦。
例如:
- 查找與
full text search
這個(gè)詞語(yǔ)最佳匹配的文檔 - 查找包含單詞
run
抚岗,但是也包含runs
,running
,jog
或sprint
的文檔 - 同時(shí)包含著
quick
,brown
和fox
--- 單詞間離得越近宣蔚,該文檔的相關(guān)性越高 - 標(biāo)識(shí)著
lucene
,search
或java
--- 標(biāo)識(shí)詞越多胚委,該文檔的相關(guān)性越高
一條查詢語(yǔ)句會(huì)計(jì)算每個(gè)文檔與查詢語(yǔ)句的相關(guān)性亩冬,然后給出一個(gè)相關(guān)性評(píng)分 _score
硅急,并且按照相關(guān)性對(duì)匹配到的文檔進(jìn)行排序铜秆。
2.2讶迁、Filter DSL
在上下文過(guò)濾語(yǔ)境中巍糯,查詢語(yǔ)句主要解決文檔是否匹配的問(wèn)題祟峦,而不會(huì)在意匹配程度(相關(guān)性評(píng)分)。
例如:
-
created
的日期范圍是否在2013
到2014
? -
status
字段中是否包含單詞 "published" ? -
lat_lon
字段中的地理位置與目標(biāo)點(diǎn)相距是否不超過(guò)10km ?
2.3针姿、比較
相關(guān)度:
-
filter
—— 只根據(jù)搜索條件過(guò)濾出符合的文檔距淫,將這些文檔的評(píng)分固定為1,忽略 TF/IDF 信息蓬衡,不計(jì)算相關(guān)度分?jǐn)?shù)狰晚; -
query
—— 先查詢符合搜索條件的文檔缴啡, 然后計(jì)算每個(gè)文檔對(duì)于搜索條件的相關(guān)度分?jǐn)?shù)壁晒,再根據(jù)評(píng)分倒序排序秒咐。
性能:
-
filter
性能更好,無(wú)排序 —— 不計(jì)算相關(guān)度分?jǐn)?shù)娘汞,不用根據(jù)相關(guān)度分?jǐn)?shù)進(jìn)行排序夕玩,同時(shí) ES 內(nèi)部還會(huì)緩存(cache)比較常用的 filter 的數(shù)據(jù) (使用bitset <0或1> 來(lái)記錄包含與否)禽作; -
query
性能較差旷偿, 有排序 —— 要計(jì)算相關(guān)度分?jǐn)?shù), 要根據(jù)相關(guān)度分?jǐn)?shù)進(jìn)行排序萍程, 并且沒(méi)有cache功能茫负。
原則上來(lái)說(shuō)忍法,使用查詢語(yǔ)句做全文本搜索或其他需要進(jìn)行相關(guān)性評(píng)分的時(shí)候,剩下的全部用過(guò)濾語(yǔ)句勉失。
在進(jìn)行搜索時(shí)戴质,常常會(huì)在查詢語(yǔ)句中告匠,結(jié)合查詢和過(guò)濾來(lái)達(dá)到查詢目的:
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }}
],
"filter": {
"range": { "date": { "gte": "2014-01-01" }}
}
}
}
三后专、重要的查詢過(guò)濾語(yǔ)句
3.1戚哎、match
match
查詢是一個(gè)標(biāo)準(zhǔn)查詢型凳,不管全文本查詢還是精確查詢基本上都要用到它嘱函。
如果使用 match
查詢一個(gè)全文本字段往弓,它會(huì)在真正查詢之前用分析器先分析查詢字符:
{
"match": {
"tweet": "About Search"
}
}
如果用match
下指定了一個(gè)確切值函似,在遇到數(shù)字,日期顿天,布爾值或者not_analyzed
的字符串時(shí)露氮,它將搜索給定的值:
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
提示: 做精確匹配搜索時(shí)钟沛,最好用過(guò)濾語(yǔ)句恨统,因?yàn)檫^(guò)濾語(yǔ)句可以緩存數(shù)據(jù)三妈。
3.2畴蒲、multi_match
multi_match
查詢?cè)试S做match
查詢的基礎(chǔ)上同時(shí)搜索多個(gè)字段:
{
"multi_match": {
"query": "full text search",
"fields": [ "title", "body" ]
}
}
3.3、match_phrase
短語(yǔ)查詢掩宜,精確匹配牺汤。查詢a red
會(huì)匹配包含a red
短語(yǔ)的檐迟,而不會(huì)進(jìn)行分詞查詢,也不會(huì)查詢出包含a 其他詞 red
這樣的文檔溶其。
{
"query": {
"match_phrase": {
"ad": "a red"
}
}
}
3.4、match_all
使用match_all
可以查詢到所有文檔每瞒,是沒(méi)有查詢條件下的默認(rèn)語(yǔ)句:
{
"match_all": {}
}
此查詢常用于合并過(guò)濾條件剿骨。 比如說(shuō)需要檢索所有的郵箱浓利,所有的文檔相關(guān)性都是相同的贷掖,所以得到的_score
為1苹威。
3.5牙甫、term
term
主要用于精確匹配哪些值,比如數(shù)字泻轰,日期浮声,布爾值或 not_analyzed
的字符串(即不進(jìn)行分詞器分析旋奢,文檔中必須包含整個(gè)搜索的詞匯):
{ "term": { "age": 26 }}
{ "term": { "date": "2014-09-01" }}
{ "term": { "public": true }}
{ "term": { "tag": "full_text" }}
3.6黄绩、terms
terms
跟 term
有點(diǎn)類似爽丹,但 terms
允許指定多個(gè)匹配條件。 如果某個(gè)字段指定了多個(gè)值真仲,那么文檔需要一起去做匹配,類似于 MySQL 的 in 條件:
{
"terms": {
"tag": [ "search", "full_text", "nosql" ]
}
}
3.7软啼、range
range
允許按照指定范圍查找一批數(shù)據(jù):
{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}
范圍操作符包含:
-
gt
:: 大于 -
gte
:: 大于等于 -
lt
:: 小于 -
lte
:: 小于等于
3.8祸挪、exists
用于查找那些指定字段中有值或無(wú)值的文檔贿条。
指定title
字段有值:
{
"exists": {
"field": "title"
}
}
指定title
字段無(wú)值:
{
"query": {
"bool": {
"must_not": {
"exists": {
"field": "group"
}
}
}
}
}
注:missing 查詢無(wú)值已經(jīng)被取消。
3.9公黑、bool
bool
可以用來(lái)合并多個(gè)條件查詢結(jié)果的布爾邏輯奠骄,它包含一下操作符:
-
must
:: 多個(gè)查詢條件的完全匹配含鳞,相當(dāng)于and
-
should
:: 至少有一個(gè)查詢條件匹配芹务,相當(dāng)于or
-
must_not
:: 多個(gè)查詢條件的相反匹配蝉绷,相當(dāng)于not
,忽略相關(guān)性評(píng)分 -
filter
:: 必須匹配枣抱,忽略相關(guān)性評(píng)分
POST /_search
{
"query": {
"bool" : {
"must" : {
"term" : { "last_name" : "smith" }
},
"filter": {
"term" : { "info.interests" : "musics" }
},
"must_not" : {
"range" : {
"info.age" : { "gte" : 10, "lte" : 25 }
}
},
"should" : [
{ "term" : { "full_name" : "john" } },
{ "term" : { "full_name" : "smith" } }
]
}
}
}
提示: 如果bool
查詢下沒(méi)有must
子句熔吗,那至少應(yīng)該有一個(gè)should
子句。但是 如果有must
子句佳晶,那么沒(méi)有should
子句也可以進(jìn)行查詢桅狠。
四、驗(yàn)證查詢
查詢語(yǔ)句可以變得非常復(fù)雜轿秧,特別是與不同的分析器和字段映射相結(jié)合后中跌,就會(huì)有些難度。
validate
API 可以驗(yàn)證一條查詢語(yǔ)句是否合法菇篡。
GET /gb/tweet/_validate/query
{
"query": {
"tweet" : {
"match" : "really powerful"
}
}
}
請(qǐng)求的返回值說(shuō)明這條語(yǔ)句是非法的:
{
"valid" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
}
}
想知道語(yǔ)句非法的具體錯(cuò)誤信息驱还,需要加上 explain
參數(shù):
GET /gb/tweet/_validate/query?explain
{
"query": {
"tweet" : {
"match" : "really powerful"
}
}
}
explain
參數(shù)可以提供語(yǔ)句錯(cuò)誤的更多詳情咐容,很顯然鸟雏,這里把 query 語(yǔ)句的 match
與字段名位置弄反了。
五锰悼、參考資料
ES 權(quán)威指南