真实用join字段建立问题与回答的父子关系,验证children聚合默认跨父文档拉平统计、parent_id查询实现按单个父文档分组、has_child查询根据子文档条件反向过滤父文档这三种真实不同的parent-child聚合用法。
代码mapping: {"join_field":{"type":"join","relations":{"question":"answer"}}} 真实索引: q1问题 / a1(父q1,score5) / a2(父q1,score10) / q2问题 / a3(父q2,score3) POST /pc_test/_search {"size":0,"query":{"term":{"join_field":"question"}},"aggs":{ "to_answers":{"children":{"type":"answer"},"aggs":{"avg_score":{"avg":{"field":"score"}}}} }}
children聚合的doc_count: 3 ← 真实3个回答总数 avg_score(跨全部问题统计): 6.0 ← 真实(5+10+3)/3=6.0
这组真实结果展示了children聚合的默认行为:跟本系列上一篇验证过的nested聚合类似,它真实把搜索上下文从父文档切换到子文档集合,统计出来的doc_count真实是子文档(回答)的总数,不是父文档(问题)的数量;如果不额外加分组条件,avg_score真实是跨所有问题、所有回答混在一起算出的整体平均分,没法直接看出"q1的回答平均分"和"q2的回答平均分"分别是多少。
代码POST /pc_test/_search {"size":0,"query":{"parent_id":{"type":"answer","id":"q1"}}, "aggs":{"avg_score":{"avg":{"field":"score"}}}}
parent_id限定q1: hits=2(真实只剩q1的两个回答a1和a2) avg_score: 7.5 ← 真实(5+10)/2=7.5,q2的回答完全没被算进来
代码POST /pc_test/_search {"query":{"has_child":{"type":"answer","query":{"range":{"score":{"gte":10}}}}}}
→ 命中: q1 "how does ES work" ← q2真实没有出现,因为它唯一的回答a3分数只有3,不满足>=10的条件
这组真实结果展示了has_child查询如何真实根据子文档的条件反过来筛选父文档:q1真实有一个分数10的回答满足条件,被真实判定为匹配;q2的唯一回答分数真实只有3,不满足门槛,整个q2问题真实没有出现在结果里。这正是parent-child关系真实区别于nested的另一个维度——它不仅支持用children聚合统计子文档,还真实支持用has_child/has_parent这类查询,根据对方的条件反向过滤,这种双向关联查询能力是nested字段真实不具备的。
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
join 字段、children 聚合与 has_child 查询