must和should联合使用失效问题

本文参考的是文章是:
ES 的shoud和must共用不生效问题
但是这篇博文中最终给出的DSL语法是错误的

在练习的时候,有这样一个需求:

查询姓氏为,且住址是北京或者上海的人员信息

这个时候会想到使用bool查询:

{
    "query":{
        "bool":{
            "must":[
                {
                    "match":{
                        "firstname":"张"
                    }
                }
            ],
            "should":[
                {
                    "match":{
                        "address":"北京"
                    }
                },
                {
                    "match":{
                        "address":"上海"
                    }
                }
            ]
        }
    },
   "size":1000
}

通过查询结果可以看出来,不仅地址是北京或者上海的人被搜索出来了,而且其他省份的人信息也被搜索出来了,这个时候should查询时没有起作用的,经过分析,原因在于DSL代码逻辑存在问题:

我们的需求是:查询姓氏为,且住址是北京或者上海的人员信息,用数学表达书表示为:
(firstname="张") &&(address=北京 || address=上海)
也可以看做是:
(firstname="张"&& address=北京) || (firstname="张" && address=上海)

这点存疑?
现在再来看看上面DSL查询语句的逻辑是: should和must之间并没有指明逻辑关系,因此它只执行了match部分,并没有执行should部分,从搜索结果来看,如果两者单纯的并列的话,那么谁在前就执行谁,后面的就不再执行了。
如上面的语句仅仅会搜索姓氏为张的所有人信息,不管他是哪里的都会显示出来;
如果两者交换位置,那么只会搜索地址为北京或者上海的人信息,不管他姓什么。

为了使得两者都能够起作用,我们可以首先将需求转换成数学逻辑语言,再根据此逻辑编写DSL(使用时去掉注释):

{
	"query":{
		"bool":{
			"should":[    //must和should用活关系连接
				{	"bool":{           //firstname="张"&& address=北京
						"must":[
							{
								"match":{
									"firstname":"张"
								}
							},
							{
								"match":{
									"address":"北京"
								}
							}
						]
					}
				},
				{
					"bool":{     //firstname="张" && address=上海
						"must":[
							{
								"match":{
									"firstname":"张"
								}
							},
							{
								"match":{
									"address":"上海"
								}
							}
						]
					}
				}
			]
			
		}
	}
}

或者写成这样子(使用时去掉注释):

{
	"query":{
		"bool":{
			"must":[   //must和should用must连接
				{	"bool":{
						"must":[     //firstname="张" 必须满足条件
							{
								"match":{
									"firstname":"张"
								}
							}
						]
					}
				},
				{
					"bool":{
						"should":[   //address=北京 || address=上海
							{
								"match":{
									"address":"北京"
								}
							},
							{
								"match":{
									"address":"上海"
								}
							}
						]
					}
				}
			]
			
		}
	}
}

Java语言的写法是:

//(firstname="张") &&(address=北京 || address=上海)
QueryBuilder queryBuilder =  QueryBuilders.boolQuery()        
                         .must(QueryBuilders.boolQuery()                
                                        .must(QueryBuilders.matchQuery("firstname","张"))        //firstname=张
                         )                                                                    
                         .must(QueryBuilders.boolQuery()                
                                       .should(QueryBuilders.matchQuery("address","北京"))                           
                                       .should(QueryBuilders.matchQuery("address","上海"))      // address=北京 || address=上海    
                        );


// (firstname="张"&& address=北京) || (firstname="张" && address=上海)
QueryBuilder queryBuilder = QueryBuilders.boolQuery()        
                    .should(QueryBuilders.boolQuery()                
                                    .must(QueryBuilders.matchQuery("firstname","张"))                    
                                    .must(QueryBuilders.matchQuery("address","北京"))        
                   )        
                   .should(QueryBuilders.boolQuery()               
                                    .must(QueryBuilders.matchQuery("firstname","张"))                
                                    .must(QueryBuilders.matchQuery("address","上海"))        
                  );

既然must和should联合使用存在这样的问题,那么must、should、must_not联合使用,也可能会存在这样的问题,解决思路一样。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章