最近有个requst,里面的docCount被展示到UI,后面会有所有聚合查询bucket的统计数据,但是最后发现怎么把bucket数据docCount相加却少于外层的docCount,于是去debug了一下记录。
我的query是这样(那个qb是我其他的BoolQueryBuilder限制一些条件的,和聚合查询无关,就不展示了)
debug之后发现问题的根源是这个:
第一次查找解决方案的时候找到了这个解释 :
在 Elasticsearch 的聚合查询中,sumOtherDocCount 表示未参与计算的文档数量之和,一般出现在 terms aggregation 中,表示某些值没有被聚合到结果中。
在你的查询语句中,sumOtherDocCount 出现在了 date_histogram aggregation 中,这可能是因为你在对 raw_timestamp 字段执行日期直方图聚合时,日期区间内存在一些文档没有 raw_timestamp 字段,或者该字段的值为空。这些文档就不会参与聚合计算,导致 sumOtherDocCount 出现。
为了解决这个问题,你可以在 date_histogram aggregation 中使用 min_doc_count 参数来指定在聚合计算中至少要有多少文档参与计算
于是加上了:
然而还是有这个问题,只有继续查找,然后找到了:
如果在你的查询中,只有子聚合 terms("cat") 出现了 sumOtherDocCount,那么可能是因为该聚合的桶数量过多,导致某些桶没有被统计到结果中。你可以尝试增大 size 参数来扩大聚合结果的桶数量
然后修改代码最终版本,将 terms("cat") 聚合的 size 参数设置为10000,以扩大聚合结果的桶数量,从而避免出现 sumOtherDocCount:
Query sq = new NativeSearchQueryBuilder()
.withQuery(qb)
.addAggregation(AggregationBuilders.dateHistogram("date_histogram")
.field("raw_timestamp")
.calendarInterval(DateHistogramInterval.DAY)
.minDocCount(1)
.subAggregation(AggregationBuilders.terms("cat").field("id.keyword").size(10000).minDocCount(1)
.subAggregation(AggregationBuilders.terms("msg").field("processed_content.keyword")
.minDocCount(1))))
.withPageable(Pageable.unpaged())
.build();
完美解决了
扩充
需要注意的是,.size需要加在AggregationBuilders上,而是不是subAggregations上,这两个都可以加而不报错,所以需要检查下,我来写扩充的原因就是之后写代码的时候不小心多打了个括号加在了subAggregations上,编译没有报错,但是又出现了sumOtherDocCount,但是困扰了很久,重新写了一次查询语句才发现。
如果还是有的话就加上 .withTrackTotalHits(true)
withTrackTotalHits(true) 是 Elasticsearch 查询中的一个参数,它用于控制搜索响应中是否精确跟踪与查询匹配的文档数。当设置为 true 时,搜索响应将始终精确跟踪与查询匹配的文档数(例如,当 track_total_hits 设置为 true 时,total.relation 将始终等于 "eq")。否则,搜索响应中的 "total.relation" 将确定如何解释 "total.value"1。
在 Elasticsearch 7.x 版本中,默认情况下,搜索响应仅返回最多 10,000 个匹配文档的计数
Query sq = new NativeSearchQueryBuilder()
.withQuery(qb)
.addAggregation(AggregationBuilders.dateHistogram("date_histogram")
.field("raw_timestamp")
.calendarInterval(DateHistogramInterval.DAY)
.minDocCount(1)
.subAggregation(AggregationBuilders.terms("cat").field("id.keyword").size(10000).minDocCount(1)
.subAggregation(AggregationBuilders.terms("msg").field("processed_content.keyword")
.minDocCount(1))))
.withPageable(Pageable.unpaged())
.withTrackTotalHits(true)
.build();