具有弹簧数据弹性搜索的特定字段的文档,最小值和最大值

时间:2015-11-03 22:53:17

标签: java spring elasticsearch spring-data spring-data-elasticsearch

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

根据我发现的一些例子以及一些修修补补,我想出了这个,但我不太确定从哪里开始,或者这是否能实现我想要的目标。

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;
    }
}

1 个答案:

答案 0 :(得分:2)

您走在正确的道路上,您只需要获取具有最大exec_time_epoch值的一个文档,为此您可以在terms聚合内添加另一个top_hits sub-aggregation check_id的{​​{1}},按照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();
    }
});