ElasticSearch學(xué)習(xí)之多條件組合查詢驗證及示例分析
多條件組合查詢
bool
es中使用bool來控制多條件查詢,bool查詢支持以下參數(shù):
must:被查詢的數(shù)據(jù)必須滿足當(dāng)前條件mush_not:被查詢的數(shù)據(jù)必須不滿足當(dāng)前條件should:被查詢的數(shù)據(jù)應(yīng)該滿足當(dāng)前條件。should查詢被用于修正查詢結(jié)果的評分。需要注意的是,如果組合查詢中沒有must,那么被查詢的數(shù)據(jù)至少要匹配一條should。如果有must語句,那么就無須匹配should,should將完全用于修正查詢結(jié)果的評分filter:被查詢的數(shù)據(jù)必須滿足當(dāng)前條件,但是filter操作不涉及查詢結(jié)果評分。僅用于條件過濾
下面通過一個例子來看下如何使用:
GET class_1/_search
{
"query": {
"bool": {
"must": [
{"match": {
"name": "apple"
}}
],
"must_not": [
{"term": {
"num": {
"value": "5"
}
}}
],
"should": [
{"match": {
"name": "k"
}}
],"filter": [
{"range": {
"num": {
"gte": 0,
"lte": 10
}
}}
]
}
}
}
結(jié)果返回:
{
"took" : 9,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.752627,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "b8fcCoYB090miyjed7YE",
"_score" : 0.752627,
"_source" : {
"name" : "I eat apple so haochi1~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "ccfcCoYB090miyjed7YE",
"_score" : 0.752627,
"_source" : {
"name" : "I eat apple so haochi3~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : 0.7389809,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
}
}
]
}
}
constant_score
constant_score查詢可以通過boost指定一個固定的評分,通常來說,constant_score的作用是代替一個只有filter的bool查詢
下面看具體使用:
GET class_1/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"num": 6
}
},
"boost": 1.2
}
}
}
返回:
{
"took" : 7,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.2,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "h2Fg-4UBECmbBdQA6VLg",
"_score" : 1.2,
"_source" : {
"name" : "b",
"num" : 6
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.2,
"_source" : {
"name" : "l",
"num" : 6
}
}
]
}
}
查詢驗證 & 分析
驗證
es中通過/_validate/query路由來驗證查詢條件的正確性, 這里要注意是驗證查詢條件是否準(zhǔn)確
示例:
GET class_1/_validate/query?explain
{
"query": {
"bool": {
"must": [
{"match": {
"name": "apple"
}}
]
}
}
}
正常返回:
{
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"valid" : true,
"explanations" : [
{
"index" : "class_1",
"valid" : true,
"explanation" : "+name:apple"
}
]
}
將name字段改為 name1再查詢:
{
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"valid" : true,
"explanations" : [
{
"index" : "class_1",
"valid" : true,
"explanation" : """+MatchNoDocsQuery("unmapped fields [name1]")"""
}
]
}
可以看到報了異常錯誤
分析
es中通過/_validate/query?explain路由來進行查詢分析
示例:
GET class_1/_validate/query?explain
{
"query": {
"bool": {
"must": [
{"match": {
"name": "apple so"
}}
]
}
}
}
返回:
{
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"valid" : true,
"explanations" : [
{
"index" : "class_1",
"valid" : true,
"explanation" : "+(name:apple name:so)"
}
]
}
可以看到"explanation" : "+(name:apple name:so)",查詢的短語apple so被進行了分詞,分成了name:apple, name: so
排序
默認排序
在前面的幾個例子中,我們可以看到它的默認排序是按照_score降序,也就是匹配度高的比較靠前,但是_socre的計算是很占用查詢性能的,這個不難理解。
當(dāng)我們不需要進行_score計算,可以通過filter或constant_score來進行構(gòu)建查詢條件
filter示例:
GET class_1/_search
{
"query": {
"bool": {
"filter": [
{"term": {
"num": 1
}}
]
}
}
}
返回:
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "b8fcCoYB090miyjed7YE",
"_score" : 0.0,
"_source" : {
"name" : "I eat apple so haochi1~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "ccfcCoYB090miyjed7YE",
"_score" : 0.0,
"_source" : {
"name" : "I eat apple so haochi3~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : 0.0,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
}
}
]
}
}
通過查詢結(jié)果我們發(fā)現(xiàn)score都為0.0了,說明沒有進行score計算
constant_score示例:
GET class_1/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"num": 1
}
},
"boost": 1.2
}
}
}
返回:
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.2,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "b8fcCoYB090miyjed7YE",
"_score" : 1.2,
"_source" : {
"name" : "I eat apple so haochi1~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "ccfcCoYB090miyjed7YE",
"_score" : 1.2,
"_source" : {
"name" : "I eat apple so haochi3~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : 1.2,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
}
}
]
}
}
可以看到,對應(yīng)返回的分值,都是使用boost屬性指定的分值
自定義排序
自定義可以用于大部分場景,那么es中怎么進行自定義排序呢? es中使用sort參數(shù)來自定義排序順序,默認為升序,那么降序怎么操作呢?
- 升序
{"sort":["num"]}
- 降序,
desc代表降序
{"sort":[{"num":{"order":"desc"}}]}
tips
es中使用doc value列式存儲來實現(xiàn)字段的排序功能text字段默認不創(chuàng)建doc value,因此無法針對text字段進行排序- 可以通過設(shè)置
text字段屬性fielddata=true來開啟對text字段的排序功能,但是不建議開啟,對text字段排序及其消耗查詢性能且不符合需求
單字段排序
GET class_1/_search
{
"sort": [
"num"
]
}
返回:
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 11,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "b8fcCoYB090miyjed7YE",
"_score" : null,
"_source" : {
"name" : "I eat apple so haochi1~",
"num" : 1
},
"sort" : [
1
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "ccfcCoYB090miyjed7YE",
"_score" : null,
"_source" : {
"name" : "I eat apple so haochi3~",
"num" : 1
},
"sort" : [
1
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : null,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
},
"sort" : [
1
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "h2Fg-4UBECmbBdQA6VLg",
"_score" : null,
"_source" : {
"name" : "b",
"num" : 6
},
"sort" : [
6
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "1",
"_score" : null,
"_source" : {
"name" : "l",
"num" : 6
},
"sort" : [
6
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "3",
"_score" : null,
"_source" : {
"num" : 9,
"name" : "e",
"age" : 9,
"desc" : [
"hhhh"
]
},
"sort" : [
9
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "4",
"_score" : null,
"_source" : {
"name" : "f",
"age" : 10,
"num" : 10
},
"sort" : [
10
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "RWlfBIUBDuA8yW5cu9wu",
"_score" : null,
"_source" : {
"name" : "一年級",
"num" : 20
},
"sort" : [
20
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "iGFt-4UBECmbBdQAnVJe",
"_score" : null,
"_source" : {
"name" : "g",
"age" : 8
},
"sort" : [
9223372036854775807
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "iWFt-4UBECmbBdQAnVJg",
"_score" : null,
"_source" : {
"name" : "h",
"age" : 9
},
"sort" : [
9223372036854775807
]
}
]
}
}
可以看到是按照num默認升序排序
再看下降序:
GET class_1/_search
{
"sort": [
{"num": {"order":"desc"}}
]
}
返回:
{
"took" : 15,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 11,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "RWlfBIUBDuA8yW5cu9wu",
"_score" : null,
"_source" : {
"name" : "一年級",
"num" : 20
},
"sort" : [
20
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "4",
"_score" : null,
"_source" : {
"name" : "f",
"age" : 10,
"num" : 10
},
"sort" : [
10
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "3",
"_score" : null,
"_source" : {
"num" : 9,
"name" : "e",
"age" : 9,
"desc" : [
"hhhh"
]
},
"sort" : [
9
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "h2Fg-4UBECmbBdQA6VLg",
"_score" : null,
"_source" : {
"name" : "b",
"num" : 6
},
"sort" : [
6
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "1",
"_score" : null,
"_source" : {
"name" : "l",
"num" : 6
},
"sort" : [
6
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "b8fcCoYB090miyjed7YE",
"_score" : null,
"_source" : {
"name" : "I eat apple so haochi1~",
"num" : 1
},
"sort" : [
1
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "ccfcCoYB090miyjed7YE",
"_score" : null,
"_source" : {
"name" : "I eat apple so haochi3~",
"num" : 1
},
"sort" : [
1
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : null,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
},
"sort" : [
1
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "iGFt-4UBECmbBdQAnVJe",
"_score" : null,
"_source" : {
"name" : "g",
"age" : 8
},
"sort" : [
-9223372036854775808
]
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "iWFt-4UBECmbBdQAnVJg",
"_score" : null,
"_source" : {
"name" : "h",
"age" : 9
},
"sort" : [
-9223372036854775808
]
}
]
}
}
這下就降序排序了
多字段
GET class_1/_search
{
"sort": [
"num", "age"
]
}
scroll分頁
還記得之前給大家講的from+size的分頁方式嗎,es中默認允許from+size的分頁的最大數(shù)據(jù)量為10000。當(dāng)我們想要批量獲取更大的數(shù)據(jù)量時,使用from+size就會十分的耗費性能。
然而大部分應(yīng)用場景下的數(shù)據(jù)量是極其龐大的,比如你要查詢某些系統(tǒng)日志數(shù)據(jù)。es中可以使用/scorll路由來進行滾動分頁查詢,它類似于在查詢初始時間點創(chuàng)建了一個當(dāng)前服務(wù)集群的數(shù)據(jù)快照(包含每一個分片),并保留它一段時間。在時間超過了設(shè)置的過期時間以后,快照將在es空閑時被刪除。
需要注意的是,因為是進行快照查詢,因此在快照創(chuàng)建后數(shù)據(jù)的變更在本次的滾動查詢中,不可見
初始化快照 & 快照保存10分鐘
查詢示例:
GET class_1/_search?scroll=10m
{
"query": {
"match_phrase": {
"name": "apple"
}
},
"size": 2
}
返回:
{
"_scroll_id" : "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAAXoFjEwWkdOMkxLUTVPZEMzM01ZdHhPc1EAAAAAAAACABZjUy1CemQwQVFfU3BUeGs2OGk0R1Z3AAAAAAAAAgEWY1MtQnpkMEFRX1NwVHhrNjhpNEdWdw==",
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.752627,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "b8fcCoYB090miyjed7YE",
"_score" : 0.752627,
"_source" : {
"name" : "I eat apple so haochi1~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "ccfcCoYB090miyjed7YE",
"_score" : 0.752627,
"_source" : {
"name" : "I eat apple so haochi3~",
"num" : 1
}
}
]
}
}
如圖,當(dāng)前共返回2條數(shù)據(jù),并且返回了一個快照ID,后續(xù)可以根據(jù)快照ID進行滾動查詢:
根據(jù)快照ID滾動查詢
GET /_search/scroll
{
"scroll": "10m",
"scroll_id" : "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAAXoFjEwWkdOMkxLUTVPZEMzM01ZdHhPc1EAAAAAAAACABZjUy1CemQwQVFfU3BUeGs2OGk0R1Z3AAAAAAAAAgEWY1MtQnpkMEFRX1NwVHhrNjhpNEdWdw=="
}
返回:
{
"_scroll_id" : "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAAXoFjEwWkdOMkxLUTVPZEMzM01ZdHhPc1EAAAAAAAACABZjUy1CemQwQVFfU3BUeGs2OGk0R1Z3AAAAAAAAAgEWY1MtQnpkMEFRX1NwVHhrNjhpNEdWdw==",
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.752627,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : 0.7389809,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
}
}
]
}
}
在滾動一次:
{
"_scroll_id" : "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAAXoFjEwWkdOMkxLUTVPZEMzM01ZdHhPc1EAAAAAAAACABZjUy1CemQwQVFfU3BUeGs2OGk0R1Z3AAAAAAAAAgEWY1MtQnpkMEFRX1NwVHhrNjhpNEdWdw==",
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.752627,
"hits" : [ ]
}
}
有的小伙伴可能不知道怎么滾動的,因為后續(xù)滾動都是同一個scroll_id,其實通過結(jié)果,我們不難發(fā)現(xiàn):
- 首先創(chuàng)建了一個10分鐘的
快照,規(guī)定了每次返回的數(shù)據(jù)量為2條,并且初始化的時候,返回了2條 - 通過
scroll_id進行滾動操作,返回了1條數(shù)據(jù),原因是快照的數(shù)據(jù)量總共只有3條,初始化的時候返回了2條,所以現(xiàn)在只有1條 - 再次滾動的時候,發(fā)現(xiàn)返回了空,因為數(shù)據(jù)已經(jīng)被查完了
以上就是ElasticSearch 多條件組合查詢驗證及示例分析的詳細內(nèi)容,更多關(guān)于ElasticSearch 多條件組合查詢的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
設(shè)置JavaScript自動提示-Eclipse/MyEclipse
自動提示需要2個組件,分別是:ext-4.0.2a.jsb2||spket-1.6.16.jar,需要的朋友可以參考下2016-05-05
Spring?Boot使用HMAC-SHA256對訪問密鑰加解密
本文主要介紹了使用HMAC-SHA256算法進行客戶端和服務(wù)端之間的簽名驗簽,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12
Elasticsearch 映射參數(shù)詳解 fields
這篇文章主要介紹了fields Elasticsearch 映射參數(shù)fields,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringCloud 搭建企業(yè)級開發(fā)框架之實現(xiàn)多租戶多平臺短信通知服務(wù)(微服務(wù)實戰(zhàn))
這篇文章主要介紹了SpringCloud 搭建企業(yè)級開發(fā)框架之實現(xiàn)多租戶多平臺短信通知服務(wù),系統(tǒng)可以支持多家云平臺提供的短信服務(wù)。這里以阿里云和騰訊云為例,集成短信通知服務(wù),需要的朋友可以參考下2021-11-11
SpringBoot+STOMP協(xié)議實現(xiàn)私聊、群聊
本文將結(jié)合實例代碼,介紹SpringBoot+STOMP協(xié)議實現(xiàn)私聊、群聊,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06

