Elastic Search条件投影:如何过滤返回结果中符合条件的nested数组元素
Elasticsearch nested数组条件投影实现方案
Elasticsearch 原生支持你需要的「按条件过滤返回nested类型数组成员」的能力,无需完全依赖业务层做二次过滤,以下是两种常用实现方式:
方案1:nested查询 + inner_hits(推荐,性能更优)
这是最常用的实现方案,利用nested查询匹配符合条件的数组成员,再通过inner_hits仅返回匹配到的成员,同时可以搭配_source控制其他返回字段。
示例请求(仅返回languageCode = en的localElements元素 + identificationString字段):
curl -X GET "localhost:9200/my-index/_search?pretty" -H 'Content-Type: application/json' -d' { "query": { "bool": { "must": [ {"match_all": {}}, { "nested": { "path": "localElements", "query": { "match": {"localElements.languageCode": "en"} }, "inner_hits": { "size": 100, // 调整为你预期的单文档nested数组最大长度,避免分页截断 "_source": ["localElements.name", "localElements.languageCode"] } } } ] } }, "_source": ["identificationString"] } '
返回结果中,hits.hits[].inner_hits.localElements.hits.hits下的内容就是过滤后的nested数组成员,和你需要的identificationString字段会并列返回。
方案2:script_fields自定义脚本过滤
如果你的过滤规则更复杂(比如多字段联合判断、数值计算等),可以用painless脚本自定义返回内容:
curl -X GET "localhost:9200/my-index/_search?pretty" -H 'Content-Type: application/json' -d' { "query": {"match_all": {}}, "_source": ["identificationString"], "script_fields": { "filtered_localElements": { "script": { "lang": "painless", "source": """ return params._source.localElements.stream() .filter(elem -> elem.languageCode == params.targetLang) .collect(Collectors.toList()); """, "params": { "targetLang": "en" } } } } } '
返回结果中hits.hits[].fields.filtered_localElements就是过滤后的nested数组。
注意事项
- 如果单文档的nested数组成员数量较多,使用
inner_hits时要调整size参数,默认值为3,可能会截断符合条件的元素。 - script_fields会遍历每个文档的nested数组,数据量较大时性能低于
inner_hits方案,优先推荐用方案1。
内容的提问来源于stack exchange,提问作者KarlMeierBE
相关产品推荐
相关产品推荐

