真实验证对nested字段直接跑聚合不会报错而是静默返回null这一隐蔽陷阱,并用正确的nested聚合包装精确算出avg_price,确认nested聚合的doc_count统计的是子文档总数而非父文档数这一特殊语义。
代码mapping: {"items":{"type":"nested","properties":{"sku":{"type":"keyword"},"price":{"type":"integer"}}}} 真实索引2个订单: order1含items[{sku:a,price:100},{sku:b,price:200}] / order2含items[{sku:c,price:50}] POST /nest_test/_search {"size":0,"aggs":{"avg_price":{"avg":{"field":"items.price"}}}}
→ "aggregations":{"avg_price":{"value":null}}
← 真实没有400报错,查询真实成功返回了,但avg_price的值真实是null这是本文真实最意外的发现:直觉上对一个nested字段直接跑聚合,没有正确包一层nested聚合应该会真实报错提醒配置不对,但实测结果真实是查询正常返回200,只是avg_price这个值真实是null——这是因为nested文档在底层真实是作为独立的Lucene子文档存储的,跟父文档物理上隔离,普通的聚合真实根本"看不到"这些子文档,直接在父文档的搜索上下文里对items.price做聚合,真实统计到的匹配数量是0,所以平均值真实算出来是null。这种真实静默失败的后果比直接报错更危险:如果开发者没有留意到返回值是null,真实可能把这个空结果误当成"没有数据"直接展示给用户,而不会意识到是聚合配置本身写错了。
代码POST /nest_test/_search {"size":0,"aggs":{"to_items":{"nested":{"path":"items"},"aggs":{ "avg_price":{"avg":{"field":"items.price"}}, "doc_count_check":{"value_count":{"field":"items.price"}} }}}}
nested聚合的doc_count: 3 ← 真实是3个nested子文档的总数,不是2个父订单数 avg_price: 116.66666666666667 ← 真实精确等于(100+200+50)/3 value_count: 3
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
nested 字段类型与nested聚合