一、问题现象
最近,在使用es做数据查询时,用了must与should组合查询,发现should下所有条件都不满足得时候,竟然也能查询出来结果。
must和should同时使用,如下例子
{
"from": 0,
"size": 20,
"query": {
"bool": {
"must": [
{
"term": {"order_id": { "value": 2133456244}}
},
{
"term": {"sku_id": {"value": 1000342267312}}
}
],
"should": [
{
"term": {"creator": {"value": "zhangsanhh"}}
},
{
"terms": {"dept_id_1": [8636,4460]
}
}
]
}
}
}
这时候会发现,当must下的条件都满足的时候,查询结果发现没有满足should下的任何一个条件的数据也包含在结果集内,should好像最小匹配了,变得可有可无了,should or的作用失效了。这显然不是我们想要的查询结果
二、问题分析
原因是我们忽略了隐藏的minimum_should_match参数,表示至少应该匹配的条件数量,其值是数字和百分比均可以。其含义取决于查询中的should 子句的数量。
当取值是整数的时候,表示至少需要匹配的 should 条件数量。当取值是一个百分比时,它表示基于should 条件的总数的相对比例。
在bool查询时候,should是选择性匹配,是or的关系,minimum_should_match默认值是1,也即至少满足一个条件匹配才能查询结果,这个与我们期望的一致。
但是在bool查询下,如果使用must、must_not、filter关键字查询,这时候bool下还带有与之平级的should条件,这时候should条件就失效了,minimum_should_match默认值变为0,should下查询条件满足0个也查询出结果。解决方案有两如下种
三、解决方案
(1)should降级
一种把should单独包装为一个bool,降级到must下,把其整体作为must下的一个条件查询
{
"from": 0,
"size": 20,
"query": {
"bool": {
"must": [{
"term": {"order_id": {"value": 2133456244}}
},
{
"term": {"sku_id": {"value": 1000342267312}}
}, {
"bool": {
"should": [{
"term": {"creator": {"value": "zhangsanhh"}}
},
{
"terms": {"dept_id_1": [8636, 4460]}
}
]
}
}
]
}
}
}
(2)指定minimum_should_match
另一种是在查询中增加minimum_should_match参数,指定值1,表示should下条件要至少满足一个条件的时候才返回数据
{
"from": 0,
"size": 20,
"query": {
"bool": {
"must": [
{
"term": {"order_id": { "value": 2133456244}}
}
],
"should": [
{
"term": {"creator": {"value": "zhangsanhh"}}
},
{
"terms": {"dept_id_1": [8636,4460]
}
}
],
"minimum_should_match": 1,
}
}
}
三、总结反思
我们在使用一种不熟悉或者新的技术时候,不要根据对已有中间件的技术点或者经验做类比,要充分理解使用中间件技术点的作用域,做好实地测试。不能忽略中间件的个性。