ElaticSearch进阶(3)_bool查询

布尔查询把多个子查询组合(combine)成一个布尔表达式,所有子查询之间的逻辑关系是与(and);只有当一个文档满足布尔查询中的所有子查询条件时,ElasticSearch引擎才认为该文档满足查询条件。

布尔查询支持的子查询类型共有四种,分别是:must,should,must_not和filter:

  • must子句:文档必须匹配must查询条件;
  • should子句:文档应该匹配should子句查询的一个或多个;
  • must_not子句:文档不能匹配该查询条件;
  • filter子句:过滤器,文档必须匹配该过滤条件,跟must子句的唯一区别是,filter不影响查询的score;

通常情况下,should子句是数组字段,包含多个should子查询,默认情况下,匹配的文档必须满足其中一个子查询条件。

注意:布尔查询的四个子句,都可以是数组字段,因此,支持嵌套逻辑操作的查询。

1.布尔查询子句的逻辑关系

在布尔查询中,各个子句之间的逻辑关系是与(and)。对于单个子句,只要一个文档满足该子句的查询条件,返回的逻辑结果就是true,而对于should子句,它一般包含多个子查询条件,参数 minimum_should_match 控制文档必须满足should子句中的子查询条件的数量,只有当文档满足指定数量的should查询条件时,should子句返回的逻辑结果才是true。

{
    "bool" : {
        "must" : {
            "term" : { "user" : "kimchy" }
        },
        "filter": {
            "term" : { "tag" : "tech" }
        },
        "must_not" : {
            "range" : {
                "age" : { "from" : 10, "to" : 20 }
            }
        },
        "should" : [
            {  "term" : { "tag" : "wow" } },
            {  "term" : { "tag" : "elasticsearch" } }
        ],
        "minimum_should_match" : 1
    }
}

在上述布尔查询中,should子句中包含两个词条查询,由于参数 minimum_should_match的值是1,因此,只要一个稳定满足任意一个词条查询的条件,should子句就匹配成功,返回逻辑结果true,然后和其他子查询进行逻辑运算,只有当该文档满足所有的子查询条件时,才作为查询结果返回到客户端。

使用布尔查询实现复杂的分组查询
复杂的分组查询,例如:(A and B) or (C and D) or (E and F) ,把布尔查询作为should子句的一个子查询:

"query": {
  "bool": {
    "should": [
     {
        "bool": {
          "must": [
            { "term": { "topics": 1}  },
            { "term": { "topics": 2}  }
          ]
        }
      },
      {
        "bool": {
          "must": [
            {"term": { "topics": 3 } },
            {"term": { "topics": 4}}
          ]
        }
      }
    ],
    "minimum_should_match": 1
  }
}

2.例子

1、搜索发帖日期为2017-01-01,或者帖子ID为XHDK-A-1293-#fJ3的帖子,同时要求帖子的发帖日期绝对不为2017-01-02

以上需求类似sql:

select *
from forum.article
where (post_date='2017-01-01' or article_id='XHDK-A-1293-#fJ3')
and post_date!='2017-01-02'

复合查询语句

思考:这个查询语句应该怎么写
其实这里我们有两个条件
(1) post_date='2017-01-01' or article_id='XHDK-A-1293-#fJ3'
(2) post_date!='2017-01-02'

条件1是or关系,所以使用should,条件2是不能匹配,所以使用must_not
{
	"query":{
		"bool":{
			"should":[{},{}],
			"must_not":{}
		}
	}
}

最终如下:
GET http://localhost:9202/forum/article/_search
{
	"query":{
		"bool":{
			"should":[
				{"term":{"postDate":"2017-01-01"}},
				{"term":{"articleID":"XHDK-A-1293-#fJ3"}}
			],
			"must_not":{
				"term":{"postDate":"2017-01-02"}
			}
		}
	}
}

2、搜索帖子ID为XHDK-A-1293-#fJ3,或者是帖子ID为JODL-X-1937-#pV7而且发帖日期为2017-01-01的帖子
以上需求类似sql:

select *
from forum.article
where article_id='XHDK-A-1293-#fJ3'
or (article_id='JODL-X-1937-#pV7' and post_date='2017-01-01')

相比于上一个sql,这里用到了嵌套查询

这里其实是一个should子句中有两个条件,只要匹配其中一个即可
{
	"query":{
		"bool":{
			"should":[
				{条件1},
				{条件2}
			],
		}
	}
}
条件1非常简单,就是精确匹配{"term":{"articleID":"XHDK-A-1293-#fJ3"}}
条件2则相对复杂的,涉及到嵌套查询,需要使用到must[{},{}],而如果使用must,则必须要在bool中使用,因为should中无法直接写must子句

GET  http://localhost:9202/forum/article/_search
{
	"query":{
		"bool":{
			"should":[
				{"term":{"articleID":"XHDK-A-1293-#fJ3"}},
				{
					"bool":{
						"must":[
							{"term":{"articleID":"JODL-X-1937-#pV7"}},
							{"term":{"postDate":"2017-01-01"}}
						]
					}
				}
			]
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值