Elasticsearch嵌套查询无法处理多个MUST条件问题排查
Elasticsearch嵌套查询多条件AND逻辑失效问题分析
环境与索引映射
使用Elasticsearch 6.5版本,创建的hotel类型索引映射如下:
{"hotel": {"mappings": {"hotel": {"properties": {"hotelAmenities": {"type": "nested","properties": {"enabled": {"type": "boolean"},"featured": {"type": "boolean"},"key": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"name": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}}}},"hotelStatus": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"name": {"type": "text","fields": {"verbatim": {"type": "keyword"}},"analyzer": "english"}}}}}
示例文档
{"name": "Hotel with amenities","hotelStatus": "BOOKABLE","hotelAmenities": [{"key": "POOL","name": "Pool","enabled": true,"featured": true},{"key": "LAUNDRY","name": "Laundry","enabled": true,"featured": true}]}
问题现象
意图实现酒店同时具备POOL和LAUNDRY设施的AND逻辑,但仅单个嵌套字段查询能返回结果,多个MUST条件并存时无法找到匹配文档。
以下是两种尝试的查询写法:
第一种写法
{"from": 0,"size": 200,"query": {"bool": {"must": [{"nested": {"query": {"bool": {"must": [{"match": {"hotelAmenities.name": "laundry"}},{"match": {"hotelAmenities.name": "pool"}}],"adjust_pure_negative": true,"boost": 1.0}},"path": "hotelAmenities","ignore_unmapped": false,"score_mode": "max","boost": 1.0}}],"must_not": [{"match": {"hotelStatus": {"query": "DECOMMISSIONED","operator": "OR","prefix_length": 0,"max_expansions": 50,"fuzzy_transpositions": true,"lenient": false,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"boost": 1.0}}}]},"adjust_pure_negative": true,"boost": 1.0}},"post_filter": {"geo_distance": {...}},"version": true}
第二种写法
{"from": 0,"size": 200,"query": {"bool": {"must": [{"nested": {"query": {"bool": {"must": [{"match": {"hotelAmenities.name": {"query": "laundry","operator": "OR","prefix_length": 0,"max_expansions": 50,"fuzzy_transpositions": true,"lenient": false,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"boost": 1.0}}}},{"match": {"hotelAmenities.name": {"query": "pool","operator": "OR","prefix_length": 0,"max_expansions": 50,"fuzzy_transpositions": true,"lenient": false,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"boost": 1.0}}}}],"adjust_pure_negative": true,"boost": 1.0}},"path": "hotelAmenities","ignore_unmapped": false,"score_mode": "max","boost": 1.0}}],"must_not": [{"match": {"hotelStatus": {"query": "DECOMMISSIONED","operator": "OR","prefix_length": 0,"max_expansions": 50,"fuzzy_transpositions": true,"lenient": false,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"boost": 1.0}}}]},"adjust_pure_negative": true,"boost": 1.0}},"post_filter": {"geo_distance": {...}},"version": true}
问题原因
当前写法的核心错误是:在同一个嵌套查询内部用must同时匹配两个hotelAmenities.name条件,这会要求文档中存在单个嵌套对象同时满足name=laundry和name=pool,但示例文档里这两个设施是两个独立的嵌套对象,自然无法匹配。
正确查询写法
需要为每个设施条件单独创建一个nested查询,将它们放在外层bool的must数组中,这样Elasticsearch会检查文档中是否分别存在匹配laundry和pool的嵌套对象,从而实现AND逻辑:
{ "from": 0, "size": 200, "query": { "bool": { "must": [ { "nested": { "query": { "match": { "hotelAmenities.name": "laundry" } }, "path": "hotelAmenities", "score_mode": "max" } }, { "nested": { "query": { "match": { "hotelAmenities.name": "pool" } }, "path": "hotelAmenities", "score_mode": "max" } } ], "must_not": [ { "match": { "hotelStatus": "DECOMMISSIONED" } } ] } }, "post_filter": {"geo_distance": {...}}, "version": true }
内容的提问来源于stack exchange,提问作者mvd
相关产品推荐
相关产品推荐

