繁体   English   中英

如何从 Java 中的聚合桶中获取 elasticsearch 聚合查询结果的值

[英]How to get value from aggregation buckets in Java for elasticsearch aggregation query result

因此,我已经能够使用 elasticsearch 高级 restclient 在 Java 中根据需要复制 elasticsearch 查询。 问题是我无法检索我想要的值。 在给出代码之前,我想解决总体目标,以防有更简单的解决方案(看起来这不应该那么困难。)

总体目标:获取 'recommender' 字段中每个唯一值的 'visited'==true 的文档数。

我目前的状态:我已经能够在 kibana/elasticsearch 中使用所需的 output 编写查询,但是当我在 Java 中复制此查询时,我无法访问我需要的数据。(使用 searchRequest.source().toString 验证())。

这是查询:

{
  "aggs":{
    "recommenderIDs": {
      "terms": {
        "field": "recommender"
      },
      "aggs": {
        "visit_stats": {
          "filters": {
            "filters": {
              "visited": {
                "match":{
                  "visited": true
                }
              }
            }
          }
        }
      }
    }
  }
}

这就是我的 java 代码中的内容:

// ...
        SearchRequest searchRequest = new SearchRequest(INDEX_REC_RECOMMENDATIONS);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String aggregationName = "recommenderId";
        String filterName = "wasVisited";
        TermsAggregationBuilder aggQuery = AggregationBuilders
                .terms(aggregationName)
                .field(RecommendationRepoFieldNames.RECOMMENDER);
        AggregationBuilder aggFilters = AggregationBuilders.filters(
                filterName,
                new FiltersAggregator.KeyedFilter(
                        RecommendationRepoFieldNames.RECOMMENDER,
                        QueryBuilders.termQuery(RecommendationRepoFieldNames.VISITED, true))
        );
        aggQuery.subAggregation(aggFilters);
        searchSourceBuilder.aggregation(aggQuery);
        searchRequest.source(searchSourceBuilder);
//        System.out.println(searchRequest.source().toString());
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            Terms byRecommenderId = aggregations.get(aggregationName);
            Filters filterResponses = searchResponse.getAggregations().get(aggregationName);
//            for (Filters.Bucket entry : filterResponses.getBuckets()) {
//                String key = entry.getKeyAsString();
//            }
            for (Terms.Bucket bucket : byRecommenderId.getBuckets()) {
                String bucketKey = bucket.getKeyAsString();
                long totalDocs = bucket.getDocCount();
                Aggregation visitedDocs = bucket.getAggregations().get(filterName);
                //long visitedDocsCount = visitedDocs.getValue();
                System.out.println();
            }
        } catch (IOException e) { //...

我整天都在摆弄这个,没有任何进展。 这尤其令人沮丧,因为当我在 IDE 中进行调试时,我可以看到每个推荐者存储桶的文档数,但我不知道如何访问它。 我意识到大约有 180 个类扩展了聚合,我尝试了一些,但每次都失败了。

此外,如果您知道 elasticsearch java 高级 rest 客户端的任何体面资源,请告诉我。 谢谢!

---------编辑 5/4/21 -------------

示例 output 来自 elasticsearch:

// searchResponse (documents returned have been truncated to show only part we are interested in)

  "aggregations": {
    "sterms#recommenderId": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "AdjacentActivityRecommender",
          "doc_count": 3,
          "filters#wasVisited": {
            "buckets": {
              "recommender": {
                "doc_count": 2
              }
            }
          }
        },
        {
          "key": "DefaultProfileDBRecommender",
          "doc_count": 2,
          "filters#wasVisited": {
            "buckets": {
              "recommender": {
                "doc_count": 2
              }
            }
          }
        },
        {
          "key": "PSTR_SC_DI",
          "doc_count": 2,
          "filters#wasVisited": {
            "buckets": {
              "recommender": {
                "doc_count": 1
              }
            }
          }
        },
        {
          "key": "SignificantCategories",
          "doc_count": 2,
          "filters#wasVisited": {
            "buckets": {
              "recommender": {
                "doc_count": 2
              }
            }
          }
        }
      ]
    }
  }

然后将 searchResponse.getAggregations() 保存到聚合中。 最终,我们能够遍历每个推荐者 ID 的存储桶,但我永远无法进入每个存储桶内部的聚合,这是我需要做的。

解决方案代码贴在下面:

    try {
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();
        Terms byRecommenderId = aggregations.get(aggregationName);
        for (Terms.Bucket bucket : byRecommenderId.getBuckets()) {
            String recommenderId = bucket.getKeyAsString();
            double totalDocs = bucket.getDocCount();
            // next two lines are the solution:
            Aggregations subAggregations = bucket.getAggregations();
            Filters byWasVisited = subAggregations.get(filterName);
            // always only one item from getBuckets()
            double totalVisited = byWasVisited.getBuckets().get(0).getDocCount();
            double percentVisited = totalVisited / totalDocs;
            recommenderViews.put(recommenderId, percentVisited);
        } 
        // ...

问题是我需要提取下一个内部级别的聚合(subAggregations),这是通过再次调用 getAggregations() 来完成的,这次是在循环内部。 此时,我们只需从 subAggregations 调用 get(filterName)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM