Elasticsearch如何实现按parent_id分组的父子层级嵌套数据查询
Elasticsearch实现树形嵌套结构查询的说明
首先给出明确结论:没有办法仅靠ES原生查询语法,一步生成你需要的“父节点内嵌children数组”的嵌套返回结构,具体原因和可落地的实现方案如下:
核心原因
- Elasticsearch的搜索、聚合逻辑天生是扁平化设计,没有内置的文档自关联递归挂载能力。哪怕用
terms按parent_id做分组聚合,输出的也是独立的桶结构,和你期望的“节点对象内嵌children数组”的格式差异极大,硬凑出来的结果冗余度极高,完全无法直接给前端消费。
可落地的实现方案
方案一:轻量查询+应用层拼接(推荐,改动成本最低)
这是绝大多数树形结构查询场景的通用实现方式,不需要修改现有线上索引结构:
- 第一步:通过ES查询拉出所有满足
id == parent_id的文档,也就是所有顶层父节点,用term查询精准匹配两个字段值相等的文档即可,性能开销极低。 - 第二步:用
terms聚合按照parent_id字段分组,拉取所有非顶层的子节点文档,拿到每个父ID对应的子节点集合。 - 第三步:在业务代码(后端服务层)做简单的遍历匹配,将每个子节点塞到对应父节点的
children数组下,就能完全生成你期望的返回结构。
方案二:改造索引结构适配原生关联查询
如果希望尽可能减少业务层的拼接逻辑,可以调整索引的字段类型:
- 建索引时定义ES原生的
join字段类型,把自关联的树形关系映射为ES的父子文档关联关系,配置好节点间的父子映射规则。 - 查询时用
has_child、has_parent语句做关联查询,但是即便用了这种结构,ES返回的结果依然是父文档、子文档独立拆分返回的,还是需要做一层简单的字段映射,没法自动生成嵌套的children数组结构。
注意:如果你的树形层级超过2层,不管用哪种实现方案,都建议在业务层做递归遍历拼接,强行依赖ES查询做多级嵌套处理,会带来很高的性能和维护成本。
内容的提问来源于stack exchange,提问作者test
相关产品推荐
相关产品推荐

