前言
目前正在出一个Es专题
系列教程, 篇幅会较多, 喜爱的话,给个重视❤️ ~
承接上文,本节把上节留传的条件查询
操作给咱们讲一下~
为了方便学习, 本节中所有示例沿用上节的索引。本文偏实战一些,好了, 废话不多说直接开整吧~
多条件组合查询
bool
es
中运用bool
来操控多条件
查询,bool
查询支持以下参数:
-
must
:被查询的数据有必要满足
当时条件 -
mush_not
:被查询的数据有必要不满足
当时条件 -
should
:被查询的数据应该满足
当时条件。should
查询被用于批改查询成果的评分。需求留意的是,假如组合查询中没有must
,那么被查询的数据至少要匹配一条should
。假如有must
句子,那么就无须匹配should
,should
将彻底用于批改查询成果的评分 -
filter
:被查询的数据有必要满足
当时条件,可是filter
操作不涉及查询成果评分。仅用于条件过滤
下面经过一个例子来看下怎么运用:
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
}
}}
]
}
}
}
成果回来:
{
"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
来进行构建查询条件
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
}
}
]
}
}
经过查询成果咱们发现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
参数来自定义排序次序,默许为升序
,那么降序
怎样操作呢?
- 升序
{"sort":["num"]}
- 降序,
desc
代表降序
{"sort":[{"num":{"order":"desc"}}]}
tips
-
es
中运用doc value
列式存储来完成字段的排序功能 -
text
字段默许不创立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
的分页的最大数据量为10000
。当咱们想要批量获取更大的数据量时,运用from+size
就会十分的消耗功能。
但是大部分应用场景下的数据量是极端巨大的,比方你要查询某些系统日志数据。es
中能够运用/scorll
路由来进行翻滚分页查询
,它类似于在查询初始时刻点创立了一个当时服务集群的数据快照
(包括每一个分片),并保留它一段时刻。在时刻超过了设置的过期时刻以后,快照将在es空闲时被删去。
需求留意的是,由于是进行快照
查询,因而在快照
创立后数据的变更在本次的翻滚查询中,不行见
初始化快照 & 快照保存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
条数据,并且回来了一个快照ID
,后续能够依据快照ID
进行翻滚
查询:
依据快照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" : [ ]
}
}
有的小伙伴或许不知道怎样翻滚
的,由于后续翻滚都是同一个scroll_id
,其实经过成果,咱们不难发现:
- 首先创立了一个10分钟的
快照
,规定了每次回来的数据量为2条
,并且初始化的时分,回来了2条 - 经过
scroll_id
进行翻滚操作,回来了1条
数据,原因是快照的数据量一共只要3条
,初始化的时分回来了2条
,所以现在只要1条
- 再次翻滚的时分,发现回来了空,由于数据现已被查完了
结束语
本节就到此结束了,咱们一定要多去操练。下节咱们进入进阶查询
部分内容 ~
本着把自己知道的都告诉咱们,假如本文对您有所帮助,点赞+重视
鼓励一下呗~
相关文章
- 利用docker建立es集群
- 一起来学ElasticSearch(一)
- 一起来学ElasticSearch(二)
- 一起来学ElasticSearch(三)
- 一起来学ElasticSearch(四)
- 一起来学ElasticSearch(五)
- 一起来学ElasticSearch(六)
项目源码(源码已更新 欢迎star⭐️)
-
spring-cloud-all
-
SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 完成授权码形式的服务认证(一)
-
SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 完成授权码形式的服务认证(二)
往期并发编程内容引荐
- Java多线程专题之线程与进程概述
- Java多线程专题之线程类和接口入门
- Java多线程专题之进阶学习Thread(含源码分析)
- Java多线程专题之Callable、Future与FutureTask(含源码分析)
- 面试官: 有了解过线程组和线程优先级吗
- 面试官: 说一下线程的生命周期进程
- 面试官: 说一下线程间的通讯
- 面试官: 说一下Java的同享内存模型
- 面试官: 有了解过指令重排吗,什么是happens-before
- 面试官: 有了解过volatile关键字吗 说说看
- 面试官: 有了解过Synchronized吗 说说看
- Java多线程专题之Lock锁的运用
- 面试官: 有了解过ReentrantLock的底层完成吗?说说看
- 面试官: 有了解过CAS和原子操作吗?说说看
- Java多线程专题之线程池的根本运用
- 面试官: 有了解过线程池的工作原理吗?说说看
- 面试官: 线程池是怎么做到线程复用的?有了解过吗,说说看
- 面试官: 堵塞行列有了解过吗?说说看
- 面试官: 堵塞行列的底层完成有了解过吗? 说说看
- 面试官: 同步容器和并发容器有用过吗? 说说看
- 面试官: CopyOnWrite容器有了解过吗? 说说看
- 面试官: Semaphore在项目中有运用过吗?说说看(源码分析)
- 面试官: Exchanger在项目中有运用过吗?说说看(源码分析)
- 面试官: CountDownLatch有了解过吗?说说看(源码分析)
- 面试官: CyclicBarrier有了解过吗?说说看(源码分析)
- 面试官: Phaser有了解过吗?说说看
- 面试官: Fork/Join 有了解过吗?说说看(含源码分析)
- 面试官: Stream并行流有了解过吗?说说看
博客(阅览体会较佳)
-
我的博客(阅览体会较佳)
-
地址
: github.com/qiuChenglei…
引荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)
-
springboot-all
-
地址
: github.com/qiuChenglei… -
SpringBoot系列教程合集
-
一起来学SpringCloud合集