我开始使用ElasticSearch并且非常喜欢它,但是我很容易陷入非常简单的情况。
我正在索引这样的工人结构:
NAME SURENAME ID AGE SEX NAME_SURENAME BIRTH_DATE
NAME_SURENAME - not analyzed - this field is indexed for grouping purposes
NAME, SURENAME - analyzed
任务很简单 - 搜索按birth_date排序的5个独特工人(唯一意味着相同的名称和确定名称,即使他们处于不同的年龄并且是不同的人)
我读到了有关聚合查询的内容,据我所知,我只能获得没有文档的聚合。不幸的是,我按名称和确定名进行汇总,所以我在桶中的结果中没有其他字段,例如至少是文档ID字段。但我也读到了关于TopHit聚合,它返回文档,我尝试了它 - 下面的第二个想法。
我有两个想法
1)不使用聚合,只搜索5个工作者,在java中过滤重复项,然后再搜索工作者并在Java中过滤重复项,直到达到5个唯一结果
2)使用聚合。我的事件尝试如下,它甚至适用于测试数据,但因为这是我的第一次,请建议,无论是意外工作还是正确完成?所以一般来说我认为我可以使用一个TopHit文档获得5个桶。我不知道如何选择TopHit文档,但似乎有效。以下是代码
String searchString = "test";
BoolQueryBuilder query = boolQuery().minimumNumberShouldMatch(1).should(matchQuery("name", searchString).should(matchQuery("surename", searchString));
TermsBuilder terms = AggregationBuilders.terms("namesAgg").size(5);
terms.field("name_surename");
terms.order(Terms.Order.aggregation("birthAgg", false)).subAggregation(AggregationBuilders.max("birthAgg")
.field("birth_date")
.subAggregation(AggregationBuilders.topHits("topHit").setSize(1).addSort("birth_date", SortOrder.DESC));
SearchRequestBuilder searchRequestBuilder = client.prepareSearch("workers")
.addAggregation(terms).setQuery(query).setSize(1).addSort(SortBuilders.fieldSort("birth_date")
.order(SortOrder.DESC));
Terms aggregations = searchRequestBuilder.execute().actionGet().getAggregations().get("namesAgg");
List<Worker> results = new ArrayList<>();
for (Terms.Bucket bucket : aggregations.getBuckets()) {
Optional<Aggregation> first = bucket.getAggregations().asList().stream().filter(aggregation -> aggregation instanceof TopHits).findFirst();
SearchHit searchHitFields = ((TopHits) first.get()).getHits().getHits()[0];
Transformer<SearchHit, Worker> transformer = transformers.get(Worker.class);
Worker transform = transformer.transform(searchHitFields);
results.add(transform);
}
return results;//