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聯合使用,也可能會存在這樣的問題,解決思路一樣。

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