must和should同时存在的坑
这个地方有个坑,就是当 must 和 should 同时存在的时候,should就成为了可有可无的了,只要must满足就可以,must就是mysql中的and, should就是or,
即 当must存在的时候,should中的条件是可有可无的,就是must条件满足就行,should的一个都不用满足也可以,当must不存在的时候,should中的条件至少要满足一个。
例如我先使用merchantName匹配一个公司,
现在我在加上该数据的merchantId必须满足should条件中的一个,你会发现并没有什么用,搜索出来的数据merchantId明明不满足我们的搜索条件之一,但是依然搜索出来了,就是因为有了must后,should中不满足也会被搜出来,
GET /xxxx/xxx/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"merchantName.keyword": "xxxxxx有限公司"
}
}
],
"should": [
{
"bool" : {
"must" : [
{
"term" : {
"merchantId" : {
"value" : 111
}
}
}
]
}
},
{
"bool" : {
"must" : [
{
"term" : {
"merchantId" : {
"value" : 112
}
}
}
]
}
}
]
}
}
}
当我们把must删除以后,会发现should生效了,此时不满足should中的条件的数据将不会被查询出来,
解决方式一
在查询条件中增加 "minimum_should_match":1,意为should条件中必须要满足其中之一,可以看到,加上该条件后,数据已经无法查出了,因为should中的条件无法满足其中之一,
去除后,则又查询出来了,
Java Api写法
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
// merchantName
queryBuilder.must(QueryBuilders.termQuery("merchantName", "xxxx"));
// should merchantId queryBuilder.should(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("merchantId", 111))); queryBuilder.should(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("merchantId", 222)));
queryBuilder.minimumShouldMatch(1);
解决方式二
之前的should和must是平级的,我们可以将should放在must的子级中也可以解决这个问题,
GET /xxx/xxx/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"merchantName.keyword": "合肥眷念商贸有限公司"
}
},
{
"bool": {
"should": [{
"bool": {
"must": [{
"term": {
"merchantId": {
"value": 111
}
}
}]
}
},
{
"bool": {
"must": [{
"term": {
"merchantId": {
"value": 112
}
}
}]
}
}
]
}
}
]
}
}
}
将条件匹配上后,则查询出来了
Java Api写法
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
// merchantName
queryBuilder.must(QueryBuilders.termQuery("merchantName", "xxxx"));
// should merchantId
BoolQueryBuilder queryDCBuilder = QueryBuilders.boolQuery();
queryDCBuilder.should(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("merchantId", 111)));
queryDCBuilder.should(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("merchantId", 222)));
queryBuilder.must(queryDCBuilder);