使用 spring 数据 elasticsearch 的特定字段的文档、最小值和最大值

Document, Min and Max for specific field with spring data elasticsearch

我正在使用 Spring Data ElasticSearch 并尝试获取其中一个字段具有最小值和最大值的不同文档。我还需要与最大值关联的文档。

基于我发现的一些例子和一些修补,我想出了这个,但我不太确定从这里去哪里或者这是否会实现我正在寻找的东西。

TermsBuilder termBuilder = AggregationBuilders.terms("check_id");
    MaxBuilder maxBuilder = AggregationBuilders.max("exec_time_epoch");
    MinBuilder minBuilder = AggregationBuilders.min("exec_time_epoch");

    termBuilder.subAggregation(maxBuilder);
    termBuilder.subAggregation(minBuilder);

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
        .withQuery(matchAllQuery())
        .addAggregation(termBuilder)
        .build();

    Aggregations aggregations = elasticsearchTemplate.query(searchQuery, new ResultsExtractor<Aggregations>() {
        @Override
        public Aggregations extract(SearchResponse response) {
            return response.getAggregations();
        }
    });

我不确定如何从中获取最小值和最大值或与最大值关联的文档。

更新:

在你的帮助下,我找到了完成这项工作的方法。这是我的完整代码,以防将来对某人有所帮助。

 public List<CamAlertDetail> findOldestAndNewest(String category) {

    TermsBuilder termBuilder = AggregationBuilders.terms("agg_terms").field("check_id");

    TopHitsBuilder topHitsBuilder = AggregationBuilders.topHits("maxDoc")
        .setSize(1)
        .addSort("exec_time_epoch", SortOrder.DESC);

    TopHitsBuilder topHitsBuilder2 = AggregationBuilders.topHits("minDoc")
        .setSize(1)
        .addSort("exec_time_epoch", SortOrder.ASC);

    termBuilder.subAggregation(topHitsBuilder);
    termBuilder.subAggregation(topHitsBuilder2);

    QueryBuilder queryBuilder;
    if (category != null) {
        queryBuilder = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("categories", category));
    } else {
        queryBuilder = matchAllQuery();
    }

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
        .withQuery(queryBuilder)
        .withIndices("caam-results")
        .addAggregation(termBuilder)
        .build();
    Aggregations aggregations = elasticsearchTemplate.query(searchQuery, new ResultsExtractor<Aggregations>() {
        @Override
        public Aggregations extract(SearchResponse response) {
            return response.getAggregations();
        }
    });

    Terms terms = aggregations.get("agg_terms");

    List<CamAlertDetail> list = new ArrayList<>();

    for (Terms.Bucket bucket : terms.getBuckets()) {
        TopHits min = bucket.getAggregations().get("minDoc");
        TopHits max = bucket.getAggregations().get("maxDoc");

        CamAlertDetail detail = new CamAlertDetail();
        detail.setOldest(createAlertFromSearchHit(min.getHits().getAt(0)));
        detail.setNewest(createAlertFromSearchHit(max.getHits().getAt(0)));
        list.add(detail);
    }

    return list;


}
    private CamAlert createAlertFromSearchHit(SearchHit hit) {

    ObjectMapper mapper = new ObjectMapper();
    try {
        return mapper.readValue(hit.sourceAsString(), CamAlert.class);
    } catch (IOException e) {
        log.error("Error Converting json to cam alert.", e);
        return null;
    }
}

你的方向是正确的,你只需要得到一个具有最大 exec_time_epoch 值的文档,为此你可以在 [=13= 中添加另一个 top_hits sub-aggregation ] check_id 的聚合,将单个文档按 exec_time_epoch.

的降序排列
TermsBuilder termBuilder = AggregationBuilders.terms("check_id");
MaxBuilder maxBuilder = AggregationBuilders.max("exec_time_epoch");
MinBuilder minBuilder = AggregationBuilders.min("exec_time_epoch");

termBuilder.subAggregation(maxBuilder);
termBuilder.subAggregation(minBuilder);

// ADD THIS: add another top_hits sub-aggregation which
// - takes a single document
// - sorted by exec_time_epoch desc
TopHitsBuilder topHitsBuilder = AggregationBuilders.topHits("maxDoc")
    .setSize(1)
    .addSort("exec_time_epoch", SortOrder.DESC);
termBuilder.subAggregation(topHitsBuilder);

SearchQuery searchQuery = new NativeSearchQueryBuilder()
    .withQuery(matchAllQuery())
    .addAggregation(termBuilder)
    .build();

Aggregations aggregations = elasticsearchTemplate.query(searchQuery, new ResultsExtractor<Aggregations>() {
    @Override
    public Aggregations extract(SearchResponse response) {
        return response.getAggregations();
    }
});