点击上方蓝色文字一键关注
点击上方“python学习专栏”,选择“置顶+星标公众号”
干货、福利第一时间送达!
数据准备
PUT student/_doc/_bulk
{"index":{"_id":1}}
{"name":"小红","age":15, "sex":"女", "class":3,"grade": 7}
{"index":{"_id":2}}
{"name":"小白","age":14, "sex":"女", "class":4,"grade": 7}
{"index":{"_id":3}}
{"name":"小绿","age":16, "sex":"女", "class":5,"grade": 9}
{"index":{"_id":4}}
{"name":"大白","age":15, "sex":"男", "class":3,"grade": 8}
{"index":{"_id":5}}
{"name":"王二狗","age":17, "sex":"男", "class":4,"grade": 7}
{"index":{"_id":6}}
{"name":"李狗蛋","age":15, "sex":"女", "class":5,"grade": 7}
{"index":{"_id":7}}
{"name":"呼延灼","age":13, "sex":"男", "class":5,"grade": 8}
{"index":{"_id":8}}
{"name":"隔壁老王","age":20, "sex":"男", "class":4,"grade": 9}
组合搜索:ES通过bool搜索将多个搜索条件进行组合,从而满足复杂搜索需求的操作。
组合搜索分为四类:
must
文档 必须 匹配这些条件才能被包含进来。
must_not
文档 必须不 匹配这些条件才能被包含进来。
should
如果满足这些语句中的任意语句,将增加评分(_score,匹配度越高排序越靠前) ,
否则,无任何影响。它们主要用于修正每个文档的相关性得分。
filter
必须 匹配,但它以不评分、过滤模式来进行。(可通过filter来提高搜索的效率)
这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。
#注意
如果没有 must 语句,那么至少需要能够匹配其中的一条 should 语句。(如果有should的情况)
但,如果存在至少一条 must 语句,则对 should 语句的匹配没有要求。
1、bool
bool不能单独存在,必须搭配子语句(must,must_not, should,filter)
根据bo0l的意思理解:就是条件成立 (true),条件不成立(false),
条件成立的文档(ES中每一条数据被称为文档)的进行返回,不满足的舍去
2、must
must:作为组合搜索中最为常用的搜索之一,它承担了多条件语句的搜索语句组合任务,通过must我们可以将多个不同条件放到一条搜索语句中(ES将搜索语句称之为DSL语句)
文章开始我们插入了一批数据
姓名 | 年龄 | 性别 | 班级 | 年级 |
13-20 | 男女 | 3-5 | 7-9 |
查询一下性别为女的数据
先使用match进行查询
GET student/_search
{
"query": {
"match": {
"sex": "女"
}
}
}
有四条数据
使用must查询
结构:
GET student/_search
{
"query": {
"bool": {
"must": [
{查询的语句,在must中可以插入多天语句,
但是每条语句都需要使用{}括起来}
]
}
}
}
例:
GET student/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"sex": { // 字段
"value": "女" //值
}
}
}
]
}
}
}
# 还可以写成这样
GET student/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"sex": "女"
}
}
]
}
}
}
四条数据
这里使用到了 term 语句,这是ES中用来判断相等的 (凡事 term内的语句值,必须相等才匹配)
除了term 还有 terms,可以传入多个值进行匹配,用法如下
例如:
terms用法
GET student/_search
{
"query": {
"bool": {
"must": [
{
"terms": {
"sex": ["女","男"]
}
}
]
}
}
}
所有的数据都查了出来
还有range,但是range语句需要注意的是,不是任何的数据类型都可以使用。一般只用于数值型和时间类型,
range用法
查询一下年龄大于等于14,小于等于18的学生
GET student/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"age": {
"gte": 14,
"lte": 18
}
}
}
]
}
}
}
range可以条件
gt | 大于 |
lt | 小于 |
gte | 大于等于 |
lte | 小于等于 |
多条件组合搜索
查询年龄在14-18,7年级五班的女生数据
GET student/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"age": {
"gte": 14,
"lte": 18
}
}
},
{
"term": {
"grade": {
"value": 7
}
}
},
{
"term": {
"class": {
"value": 5
}
}
},
{
"term": {
"sex": {
"value": "女"
}
}
}
]
}
}
}
我们查到了七年级五班的李狗蛋同学
3、must_not
must_not ,所有的满足条件数据均排除,获取不满足条件的数据
查询 所有的女生
先使用must进行查询
GET student/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"sex": "女"
}
}
]
}
}
}
使用must_not 进行查询
GET student/_search
{
"query": {
"bool": {
"must_not": [
{
"term": {
"sex": "男"
}
}
]
}
}
}
查询不是女生,不是七年级的学生
GET student/_search
{
"query": {
"bool": {
"must_not": [
{"term": {"sex": "女"}},
{"term":{"grade": 7}}
]
}
}
}
关于must_not的查询,从实现上均可以使用must进行替代,但是还是有一些数据我们不合适使用must进行查询,(之前有人跟我说尽量不使用相反查询,一开始我不是很明白为什么,竟然能够完成查询,为什么不能使用相反查询,后来再项目中用到了相反查询,才明白。举个例子:一个字段有两个状态A,B,但是A的数量比较少,为了查询B,过滤了A,但是如果有一天突然说需要为这个字段增加一个状态 C,咋办......),
因此使用must_not查询你需要保证自己的业务逻辑不会因为添加更多数据而出现逻辑错误,比如在一个公司的员工系统中查询不是领导的员工,一般而言领导少于员工(一般公司除了员工就是领导了,外聘也算员工)这时可是使用must_not进行过滤,从而优化查询的效率。
4、should
should查询一般用来对查询到的数据增加评分,但是should也能够进行查询。但是可能你需要明白使用should查询,一旦有一个条件满足,该数据就会返回。
例如:
GET student/_search
{
"query": {
"bool": {
"should": [
{"term": {"sex": "女"}},
{"term":{"grade": 7}}
]
}
}
}
不仅仅查询到了七年级的女生,还查询到了七年级男生,还有其它年级女生,因此只要有一条数据满足条件就好返回
5、filter
filter查询,所有满足条件的数据都会返回,是不是和must查询的作用一样,filter和must返回数据确实是一样的,但是不同的是返回的数据排序不同。filter过滤是不计算评分的,不会影响返回数据的评分
例如:
GET student/_search
{
"query": {
"bool": {
"filter": [
{"term": {"sex": "女"}},
{"term":{"grade": 7}}
]
}
}
}
查看返回的数据,发现评分都是一样的,仅使用filter时,评分都以0进行标注
filter过滤的不评分查询,在很多时候是比较实用的,先时间开发中经常使用filter来对不需要排序的数据进行过滤,由于filter查询不进行评分,因此查询的效率会高于其它的查询语句。因此如果你的查询不需要评分,尽量使用filter进行过滤。
如果你的查询只有filter查询,那么你可以不使用bool查询
ES提供了constant_score 查询,尽管没有 bool 查询使用这么频繁,
constant_score 查询也是需要了解的
constant_score 将一个不变的常量评分应用于所有匹配的文档。
它被经常用于你只需要执行一个 filter 而没有其它查询的情况下
例如
GET student/_search
{
"query": {
"constant_score": {
"filter": {
"term": {"sex": "女"}
}
}
}
}
constant_score 查询不进行评分,因此返回数据的评分都为 1
6.多种查询组合
例1,查询年龄小于18岁的女生,并且不是9年级的学生
GET student/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"age": {
"lte": 18
}
}},
{
"term": {
"sex": {
"value": "女"
}
}
}
],
"must_not": [
{
"term": {
"grade": {
"value": 9
}
}
}
]
}
}
}
查到三条数据,这里使用到的must_not就是不可替代的
例2:查询七年级的学生,要求女士优先(返回数据女生在前)
查询七年级,使用must,grade=7,女士优先使用should增加评分
GET student/_search
{
"query": {
"bool": {
"must": [
{"term":{"grade": 7}}
],
"should": [
{"term":{"sex":"女"}}
]
}
}
}
返回四条数据,三位女士,一位男生(为了展示,我把一些不必要的字段去掉了)
"hits" : [
"_source" : {
"name" : "小红",
"age" : 15,
"sex" : "女",
"class" : 3,
"grade" : 7
}
},
{
"_source" : {
"name" : "小白",
"age" : 14,
"sex" : "女",
"class" : 4,
"grade" : 7
}
},
{
"_source" : {
"name" : "李狗蛋",
"age" : 15,
"sex" : "女",
"class" : 5,
"grade" : 7
}
},
{
"_source" : {
"name" : "王二狗",
"age" : 17,
"sex" : "男",
"class" : 4,
"grade" : 7
}
}
]
文章就讲到这里,所涉及的深度在一般情况下都是足够使用的,当然组合查询还有一些内容没有详解,比如增加某条语句评分权重(深入部分主要就是考虑数据的排序问题,排序有时还是有用的,可以类比百度搜索),有兴趣可以到elaticsearch官网查看。
点赞+关注
END
扫描识别二维码,关注公众号,更多文章等你阅读