elasticsearch聚合查询时解决数据聚合数量之和不等于docCount问题(sumOtherDocCount问题)

最近有个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();

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Elasticsearch聚合(Aggregation)功能来查询多个索引并对索引名进行分组。具体实现步骤如下: 1. 首先创建一个SearchRequest对象,设置要查询的索引列表和查询条件。 2. 创建一个TermsAggregationBuilder对象,设置聚合的字段为索引名,并设置其它聚合参数,如聚合大小、排序等。 3. 将TermsAggregationBuilder对象添加到SearchRequest对象中的AggregationBuilder列表中。 4. 使用RestHighLevelClient执行查询,将SearchRequest对象作为参数传入search()方法。 示例代码如下: ``` SearchRequest searchRequest = new SearchRequest("index1", "index2"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("index_names").field("_index"); searchSourceBuilder.aggregation(aggregationBuilder); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); Terms indexNames = searchResponse.getAggregations().get("index_names"); for (Terms.Bucket bucket : indexNames.getBuckets()) { String indexName = bucket.getKeyAsString(); long docCount = bucket.getDocCount(); // Do something with indexName and docCount } ``` 以上示例代码中,我们查询了两个索引index1和index2,并对它们进行了分组。最后,我们使用聚合结果中的Bucket对象获取索引名和文档数量等信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值