如何在Elasticsearch中同时返回嵌套文档字段与根文档属性的投影
Elasticsearch嵌套文档关联根字段查询实现方案
你当前选择nested作为users字段类型是完全合理的,非常适配后续对嵌套子字段做过滤、排序的需求,无需调整字段类型。以下两种方案都可以在查询阶段拿到所有需要的数据,仅需极少量格式化即可得到你需要的返回格式:
方案一:Nested查询+Inner Hits(性能最优,适合单城市内用户排序场景)
该方案走查询逻辑,性能远高于聚合方案,适合不需要全局跨城市对用户做排序的场景。
查询语句
GET cities/_search { "_source": ["city"], "query": { "bool": { "filter": [ {"term": {"state": "NY"}} ], "must": [ { "nested": { "path": "users", "query": {"match_all": {}}, "inner_hits": { "_source": ["users.firstName", "users.lastname", "users.birthYear"], "sort": [{"users.birthYear": "asc"}] } } } ] } } }
结果说明
返回结果中每个命中的根文档会携带city字段,同时inner_hits.users.hits中会返回该城市下所有用户的属性,只需遍历根文档将city字段和用户属性合并即可得到目标格式。
方案二:Nested聚合+Top Hits(支持全局跨城市排序)
如果你需要对所有符合条件的用户做全局按birthYear排序,使用该方案可以直接在ES侧完成排序逻辑。
查询语句
GET cities/_search { "size": 0, "query": { "term": {"state": "NY"} }, "aggs": { "all_users": { "nested": { "path": "users" }, "aggs": { "sorted_users": { "top_hits": { "size": 100, "sort": [{"users.birthYear": "asc"}], "fields": [ "users.firstName", "users.lastname", "users.birthYear", "city" ], "_source": false } } } } } }
结果说明
返回的聚合结果中aggregations.all_users.sorted_users.hits.hits下的每条数据的fields字段已经包含了所有需要的属性,且已经按birthYear全局排序完成,直接提取即可组装为目标格式。
注意事项
- 若需要分页返回大量用户数据,建议使用方案一配合
search_after参数实现深度分页,性能优于聚合方案 - 两种方案都避免了全量拉取文档后在业务层做过滤、排序,性能损耗极低
内容的提问来源于stack exchange,提问作者user3862271
相关产品推荐
相关产品推荐

