如何在OpenSearch中用AND逻辑(filter/must)筛选同属性文档?
OpenSearch嵌套属性的AND逻辑筛选方案
问题场景
已创建OpenSearch索引test,映射定义如下:
PUT test { "mappings": { "properties": { "id": { "type": "keyword" }, "body": { "type": "text" }, "subjects": { "type": "nested", "properties": { "id": { "type": "keyword" }, "path_id": { "type": "keyword" } } } } } }
并添加了3条测试文档:
POST test/_doc { "id": "1", "body": "topic 1", "subjects": [ { "id": "calculus-ii", "path_id": ["math", "advanced-math", "calculus-ii"] }, { "id": "calculus-iii", "path_id": ["math", "advanced-math", "calculus-iii"] } ] } POST test/_doc { "id": "2", "body": "topic 2", "subjects": [ { "id": "calculus-i", "path_id": ["math", "advanced-math", "calculus-i"] }, { "id": "calculus-ii", "path_id": ["math", "advanced-math", "calculus-ii"] } ] } POST test/_doc { "id": "3", "body": "topic 3", "subjects": [ { "id": "equations", "path_id": ["math", "basic-math", "equations"] } ] }
需求是筛选出同时包含subjects.path_id: calculus-ii和subjects.path_id: calculus-iii的文档,但直接在bool的must/filter中添加两个条件会返回空结果,使用should则会返回文档1和2,需要实现正确的AND逻辑筛选。
问题原因
因为subjects是嵌套类型(nested),OpenSearch会把数组中的每个嵌套元素当作独立的子文档存储。如果直接在同一个nested查询里用must同时匹配两个path_id,相当于要求单个嵌套子文档同时包含calculus-ii和calculus-iii,而现有数据中没有符合该条件的子文档,因此查询返回空。
解决方案
要实现“文档中存在至少一个嵌套元素包含calculus-ii,且存在至少一个嵌套元素包含calculus-iii”的AND逻辑,需要在bool的must(或filter)中添加两个独立的nested查询,每个nested查询负责匹配一个条件:
用must实现(影响评分)
GET test/_search { "query": { "bool": { "must": [ { "nested": { "path": "subjects", "query": { "term": { "subjects.path_id": "calculus-ii" } } } }, { "nested": { "path": "subjects", "query": { "term": { "subjects.path_id": "calculus-iii" } } } } ] } } }
用filter实现(不影响评分,性能更优)
GET test/_search { "query": { "bool": { "filter": [ { "nested": { "path": "subjects", "query": { "term": { "subjects.path_id": "calculus-ii" } } } }, { "nested": { "path": "subjects", "query": { "term": { "subjects.path_id": "calculus-iii" } } } } ] } } }
上述查询会精准返回符合要求的文档1,因为它同时满足两个nested查询的条件。
内容的提问来源于stack exchange,提问作者Washington Guedes
相关产品推荐
相关产品推荐

