您好,登錄后才能下訂單哦!
這篇文章主要講解了“ElasticSearch查詢?cè)趺词褂谩?,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“ElasticSearch查詢?cè)趺词褂谩卑桑?/p>
有兩種方法執(zhí)行搜索:第一種是通過(guò)REST request Uri 發(fā)送搜索參數(shù),第二種是通過(guò)REST request body。第二種方法允許你用json格式定義更豐富的查詢參數(shù)。我們將會(huì)用第一種方法做一個(gè)例子,但之后都會(huì)專一地使用第二種方法做實(shí)驗(yàn)。
_search 返回 bank索引的所有文檔
GET /bank/_search?q=*&sort=account_number:asc
q=* :查詢所有
返回結(jié)果如下:
{ "took" : 82, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 1000, "max_score" : null, "hits" : [ { "_index" : "bank", "_type" : "account", "_id" : "0", "sort": [0], "_score" : null, "_source" : {"account_number":0,"balance":16623,"firstname":"Bradshaw","lastname":"Mckenzie","age":29,"gender":"F","address":"244 Columbus Place","employer":"Euron","email":"bradshawmckenzie@euron.com","city":"Hobucken","state":"CO"} }, { "_index" : "bank", "_type" : "account", "_id" : "1", "sort": [1], "_score" : null, "_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"} }, ... ] } }
took-elasticsearch執(zhí)行搜索花費(fèi)的毫秒數(shù)
timed_out-告訴我們這次搜索是否超時(shí)
_shards- 告訴我們搜索了多少個(gè)分片,以及搜索成功和失敗的分片數(shù)
hits-搜索返回的文檔結(jié)果
hits.total 一共命中了多少結(jié)果
sort-搜索排序規(guī)則,如果沒有該字段,則按相關(guān)度排序
_score和max_score 暫時(shí)先忽略這個(gè)參數(shù)(文檔得分,反映相關(guān)度)
下面用request body方法執(zhí)行和上面一樣的搜索操作:
GET /bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ] }
query
字段說(shuō)明查詢內(nèi)容
match_all
是執(zhí)行查詢操作的匹配類型 , match_all
是匹配所有文檔的意思。
不同點(diǎn)是我們用json格式的請(qǐng)求體代替了_search api uri中的q=*參數(shù)。
必須要知道的是:當(dāng)我們接收到返回結(jié)果的時(shí)候,elasticsearch已經(jīng)完全處理了這個(gè)請(qǐng)求,不會(huì)維護(hù)任何的服務(wù)器資源或游標(biāo)到你的返回結(jié)果中。這與類似sql這樣的平臺(tái)形成鮮明的對(duì)比,sql允許你先取前面的一部分?jǐn)?shù)據(jù),然后連續(xù)不斷的通過(guò)服務(wù)器端的游標(biāo)再去取剩下的數(shù)據(jù)。
除了query
參數(shù),我們也可以傳遞其他參數(shù)去影響查詢結(jié)果。在上一章節(jié)的例子我們傳遞了一個(gè)sort參數(shù),這里我們傳遞一個(gè)size
GET /bank/_search { "query": { "match_all": {} }, "size": 1 }
注意,如果size沒有指定,默認(rèn)值是10.
下面這個(gè)例子匹配所有文檔,并返回第11-20的文檔:
GET /bank/_search { "query": { "match_all": {} }, "from": 10, "size": 10 }
from參數(shù)指定從第幾個(gè)文檔開始返回,size參數(shù)指定一共返回多少個(gè)文檔。這個(gè)特性是對(duì)分頁(yè)功能是十分重要的。如果from沒有指定,默認(rèn)值是0。
下面的例子按賬戶余額倒序查詢前10個(gè)結(jié)果(默認(rèn)size大?。?/p>
GET /bank/_search { "query": { "match_all": {} }, "sort": { "balance": { "order": "desc" } } }
現(xiàn)在我已經(jīng)看見過(guò)一些基礎(chǔ)的查詢參數(shù),讓我們挖掘更多關(guān)于query DSL 的信息。首先看看返回文檔的字段。默認(rèn)所有的字段都會(huì)被返回。文檔原始內(nèi)容被稱為源(對(duì)應(yīng)hits中的_source 鍵)。如果我們不想返回文檔的所有字段,也可以僅僅要求接口返回部分字段。
下面的例子展示如何返回 account_number 和balance(在_source里面)這個(gè)兩個(gè)字段:
GET /bank/_search { "query": { "match_all": {} }, "_source": ["account_number", "balance"] }
注意上述操作只是減少了返回的字段,但是_source
字段還是存在的,只是僅返回account_number
和balance
字段
如果你曾經(jīng)學(xué)過(guò)sql,上述概念就和sql select filed list from
差不多。
現(xiàn)在,讓我們繼續(xù)學(xué)習(xí)查詢語(yǔ)法。之前,我們已經(jīng)看到過(guò)match_all
查詢類型使用來(lái)匹配所有文檔的?,F(xiàn)在,我們介紹一種新的查詢類型match
,他是基于字段搜索的(即,通過(guò)匹配一個(gè)特定的字段或一組字段執(zhí)行搜索)
下面的例子返回賬號(hào)number是20的文檔:
GET /bank/_search { "query": { "match": { "account_number": 20 } } }
下面的例子返回所有地址字段包含mill
的賬戶文檔
GET /bank/_search { "query": { "match": { "address": "mill" } } }
下面的例子返回地址字段包含“mill”或者“l(fā)ane”的賬戶
GET /bank/_search { "query": { "match": { "address": "mill lane" } } }
下面的例子是match
的變種(match_phrase
),它返回所有地址字段包含詞組“mill lane”的賬戶
GET /bank/_search { "query": { "match_phrase": { "address": "mill lane" } } }
現(xiàn)在,讓我介紹一下布爾查詢。bool
查詢?cè)试S我們把多個(gè)match
查詢合并到一個(gè)查詢中。
下面的例子合并了兩個(gè)match
查詢并返回所有地址字段同時(shí)包含“mill”和“l(fā)ane”的賬戶
GET /bank/_search { "query": { "bool": { "must": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }
上述例子的bool must
子句指定:當(dāng)所有的查詢都返回true的時(shí)候,才認(rèn)為匹配文檔。
與此相反,下面這個(gè)這個(gè)例子合并兩個(gè)match
查詢,并返回所有地址地段包含“mill”或“l(fā)ane”的賬戶
GET /bank/_search { "query": { "bool": { "should": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }
上述例子,bool should
子句只要文檔滿足其中一個(gè)查詢,就認(rèn)為匹配。
下面的例子合并了兩個(gè)match
查詢,并返回所有地址字段既不包含“mill”也不包含“l(fā)ane”的賬戶:
GET /bank/_search { "query": { "bool": { "must_not": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }
上面的例子中,bool must_not
子句指定當(dāng)所有查詢都不滿足的時(shí)候,就認(rèn)為匹配文檔。
我們也可以把must
,should
,must_not
同時(shí)組合到bool
子句。此外,我們也可以組合bool
到任何一個(gè)bool
子句中,實(shí)現(xiàn)復(fù)雜的多層bool
子句嵌套邏輯。
下面的例子返回所有年齡是40歲但不是住在ID州的賬戶:
GET /bank/_search { "query": { "bool": { "must": [ { "match": { "age": "40" } } ], "must_not": [ { "match": { "state": "ID" } } ] } } }
在之前的章節(jié),我們跳過(guò)了一個(gè)小細(xì)節(jié):文檔得分(搜索結(jié)果的_score
字段).文檔得分是一個(gè)數(shù)字值,它代表關(guān)鍵字和文檔內(nèi)容的相關(guān)度估值。 文檔得分越高說(shuō)明相關(guān)度越高,文檔得分越少,說(shuō)明相關(guān)度越少。
但查詢不一定都需要產(chǎn)生文檔得分,特別在過(guò)濾文檔集合的時(shí)候。為了避免不必要的文檔得分計(jì)算,Elasticsearch會(huì)檢查這種情況并自動(dòng)的優(yōu)化這種查詢。
在前面章節(jié)介紹的bool
查詢也支持filter
子句,它允許你使用一個(gè)查詢語(yǔ)句去過(guò)濾其它子句的匹配結(jié)果,同時(shí)不會(huì)改變文檔的得分。我們介紹一下range
查詢,并把它作為例子,它允許我們通過(guò)一個(gè)范圍值去過(guò)濾文檔。通常用于數(shù)字或日期過(guò)濾。
這個(gè)例子使用bool
查詢返回所有賬戶余額在20000-30000之間的文檔。換句話說(shuō),我們需要查找余額大于20000小于30000的賬戶:
GET /bank/_search { "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000 } } } } } } { "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000 } } } } } }
仔細(xì)分析上面的例子,bool
查詢包含了一個(gè)match_all
查詢(查詢部分)和一個(gè)range
查詢(過(guò)濾部分)。我們也可以用任何其它的查詢語(yǔ)句代替查詢和過(guò)濾部分的語(yǔ)句。對(duì)于上面的例子,因?yàn)樗形臋n都是指定范圍之內(nèi)的,他們從某種意義上來(lái)說(shuō)是等價(jià)的(equally),即他們的相關(guān)度都是一樣的(filter子句查詢,不會(huì)改變得分)。
除了 match_all
,match
,bool
,range
查詢,還有很多種類的查詢,但我們不在這里一一介紹。從現(xiàn)在開始,我們對(duì)查詢已經(jīng)有一個(gè)基礎(chǔ)的了解,把學(xué)到的知識(shí)應(yīng)用到其他查詢類型應(yīng)該也沒什么難度。
GET /bank/_search { "query": { "term": { "address": "789 Madison" } } }
GET /bank/_search { "query": { "match": { "address.keyword": "789 Madison" } } }
match
:模糊匹配,需要指定字段名,但是輸入會(huì)進(jìn)行分詞,比如"hello world"會(huì)進(jìn)行拆分為hello和world,然后匹配,如果字段中包含hello或者world,或者都包含的結(jié)果都會(huì)被查詢出來(lái),也就是說(shuō)match是一個(gè)部分匹配的模糊查詢。查詢條件相對(duì)來(lái)說(shuō)比較寬松。
term
: 這種查詢和match在有些時(shí)候是等價(jià)的,比如我們查詢單個(gè)的詞hello,那么會(huì)和match查詢結(jié)果一樣,但是如果查詢"hello world",結(jié)果就相差很大,因?yàn)檫@個(gè)輸入不會(huì)進(jìn)行分詞,就是說(shuō)查詢的時(shí)候,是查詢字段分詞結(jié)果中是否有"hello world"的字樣,而不是查詢字段中包含"hello world"的字樣,elasticsearch會(huì)對(duì)字段內(nèi)容進(jìn)行分詞,"hello world"會(huì)被分成hello和world,不存在"hello world",因此這里的查詢結(jié)果會(huì)為空。這也是term查詢和match的區(qū)別。
match_phase
:會(huì)對(duì)輸入做分詞,但是需要結(jié)果中也包含所有的分詞,而且順序要求一樣。以"hello world"為例,要求結(jié)果中必須包含hello和world,而且還要求他們是連著的,順序也是固定的,hello that word不滿足,world hello也不滿足條件。
query_string
:和match類似,但是match需要指定字段名,query_string是在所有字段中搜索,范圍更廣泛。
不同于term,keyword精確匹配要求查詢的字段必須等于
一般我們?nèi)臋z索字段用match,其他非text字段匹配用term
聚合功能能夠分組并統(tǒng)計(jì)你的數(shù)據(jù)。最簡(jiǎn)單的說(shuō)法就是等價(jià)于sql group by
語(yǔ)句和sql的聚合函數(shù)。使用elasticsearch,你可以同時(shí)在一個(gè)請(qǐng)求中返回需要查詢的數(shù)據(jù)以及這些數(shù)據(jù)的多種聚合運(yùn)算結(jié)果。在單個(gè)請(qǐng)求中就可以同時(shí)查詢數(shù)據(jù)和進(jìn)行多次聚合運(yùn)算是非常有意義的,他可以降低網(wǎng)絡(luò)請(qǐng)求的次數(shù)。
下面的例子把state
字段的內(nèi)容分組,并按照每一組的文檔數(shù)量倒序排序,返回?cái)?shù)量最多的前10(默認(rèn)值)組數(shù)據(jù):
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword" } } } }
上面的聚合運(yùn)算等價(jià)于執(zhí)行下面的sql:
SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC
返回結(jié)果(僅展示一部分):
{ "took": 29, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits" : { "total" : 1000, "max_score" : 0.0, "hits" : [ ] }, "aggregations" : { "group_by_state" : { "doc_count_error_upper_bound": 20, "sum_other_doc_count": 770, "buckets" : [ { "key" : "ID", "doc_count" : 27 }, { "key" : "TX", "doc_count" : 27 }, { "key" : "AL", "doc_count" : 25 }, { "key" : "MD", "doc_count" : 25 }, { "key" : "TN", "doc_count" : 23 }, { "key" : "MA", "doc_count" : 21 }, { "key" : "NC", "doc_count" : 21 }, { "key" : "ND", "doc_count" : 21 }, { "key" : "ME", "doc_count" : 20 }, { "key" : "MO", "doc_count" : 20 } ] } } }
我們可以看到,ID州有27個(gè)賬戶,隨后的TX州有27個(gè)賬戶,AL州有25個(gè)賬戶。
注意我們?cè)O(shè)置size=0是因?yàn)槲也恍枰樵兾臋n,只需要查詢聚合結(jié)果。
基于上述例子,下面的例子除了分組還會(huì)計(jì)算每個(gè)州的賬戶的平均余額:
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword" }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } }
注意我們是如何把a(bǔ)verage_balance聚合嵌入到group_by_state聚合中。這種模式適合于所有的聚合。你可以按你的需求重復(fù)嵌套聚合子句,匯總你的數(shù)據(jù)。
基于上面的例子,我們加入了按每個(gè)州的賬戶平均余額倒序排序的限制(說(shuō)明了上一層聚合可以使用下一層聚合的運(yùn)算結(jié)果):
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword", "order": { "average_balance": "desc" } }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } }
下面例子講述了我們?nèi)绾伟茨挲g組分組(20-29,30-39,40-49),然后按性別分組,最后獲取每個(gè)組中每個(gè)性別的賬戶平均余額。(例如:年齡段在20-29的女性用戶的賬戶平均余額)
GET /bank/_search { "size": 0, "aggs": { "group_by_age": { "range": { "field": "age", "ranges": [ { "from": 20, "to": 30 }, { "from": 30, "to": 40 }, { "from": 40, "to": 50 } ] }, "aggs": { "group_by_gender": { "terms": { "field": "gender.keyword" }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } } } }
最后一個(gè)例子,查出所有年齡分布,并且這些年齡段中性別M的平均薪資和F的平均薪資以及這個(gè)年齡段的總體平均薪資
GET /bank/_search { "size": 0, "aggs":{ "aggAgg": { "terms": { "field": "age" }, "aggs": { "ageBalanceAvg":{ "avg": { "field": "balance" } }, "genderAgg":{ "terms":{ "field": "gender.keyword" }, "aggs": { "avgAvg":{ "avg": { "field": "balance" } } } } } } } }
感謝各位的閱讀,以上就是“ElasticSearch查詢?cè)趺词褂谩钡膬?nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)ElasticSearch查詢?cè)趺词褂眠@一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。