ElasticSearch學習之多條件組合查詢驗證及示例分析
多條件組合查詢
bool
es中使用bool來控制多條件查詢,bool查詢支持以下參數(shù):
must:被查詢的數(shù)據(jù)必須滿足當前條件mush_not:被查詢的數(shù)據(jù)必須不滿足當前條件should:被查詢的數(shù)據(jù)應該滿足當前條件。should查詢被用于修正查詢結(jié)果的評分。需要注意的是,如果組合查詢中沒有must,那么被查詢的數(shù)據(jù)至少要匹配一條should。如果有must語句,那么就無須匹配should,should將完全用于修正查詢結(jié)果的評分filter:被查詢的數(shù)據(jù)必須滿足當前條件,但是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路由來驗證查詢條件的正確性, 這里要注意是驗證查詢條件是否準確
示例:
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的計算是很占用查詢性能的,這個不難理解。
當我們不需要進行_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
}
}
]
}
}
可以看到,對應返回的分值,都是使用boost屬性指定的分值
自定義排序
自定義可以用于大部分場景,那么es中怎么進行自定義排序呢? es中使用sort參數(shù)來自定義排序順序,默認為升序,那么降序怎么操作呢?
- 升序
{"sort":["num"]}
- 降序,
desc代表降序
{"sort":[{"num":{"order":"desc"}}]}
tips
es中使用doc value列式存儲來實現(xiàn)字段的排序功能text字段默認不創(chuàng)建doc value,因此無法針對text字段進行排序- 可以通過設置
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。當我們想要批量獲取更大的數(shù)據(jù)量時,使用from+size就會十分的耗費性能。
然而大部分應用場景下的數(shù)據(jù)量是極其龐大的,比如你要查詢某些系統(tǒng)日志數(shù)據(jù)。es中可以使用/scorll路由來進行滾動分頁查詢,它類似于在查詢初始時間點創(chuàng)建了一個當前服務集群的數(shù)據(jù)快照(包含每一個分片),并保留它一段時間。在時間超過了設置的過期時間以后,快照將在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
}
}
]
}
}
如圖,當前共返回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)容,更多關于ElasticSearch 多條件組合查詢的資料請關注腳本之家其它相關文章!
相關文章
SpringBoot實現(xiàn)elasticsearch 查詢操作(RestHighLevelClient 
這篇文章主要給大家介紹了SpringBoot如何實現(xiàn)elasticsearch 查詢操作,文中有詳細的代碼示例和操作流程,具有一定的參考價值,需要的朋友可以參考下2023-07-07
詳解JavaScript中的函數(shù)聲明和函數(shù)表達式
這篇文章主要介紹了詳解JavaScript中的函數(shù)聲明和函數(shù)表達式,是JS入門學習中的基礎知識,需要的朋友可以參考下2015-08-08
Java如何使用ReentrantLock實現(xiàn)長輪詢
這篇文章主要介紹了如何使用ReentrantLock實現(xiàn)長輪詢,對ReentrantLock感興趣的同學,可以參考下2021-04-04
Spring?Security實現(xiàn)統(tǒng)一登錄與權(quán)限控制的示例代碼
這篇文章主要介紹了Spring?Security實現(xiàn)統(tǒng)一登錄與權(quán)限控制,本文通過示例代碼重點看一下統(tǒng)一認證中心和業(yè)務網(wǎng)關的建設,需要的朋友可以參考下2022-03-03
Spring整合CXF webservice restful實例詳解
這篇文章主要為大家詳細介紹了Spring整合CXF webservice restful的實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
關于Java中@SuppressWarnings的正確使用方法
這篇文章主要介紹了關于Java中@SuppressWarnings的正確使用方法,@SuppressWarnings注解主要用在取消一些編譯器產(chǎn)生的警告對代碼左側(cè)行列的遮擋,有時候這會擋住我們斷點調(diào)試時打的斷點,需要的朋友可以參考下2023-05-05

