我使用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;
}
}
答案 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();
}
});