Searching without duplication - aggregations and tophit
<p>I am beginning with ElasticSearch and really like it, hovewer I am stuck with quite simple scenario.
I am indexing such structure of a Worker:
<code>NAME SURENAME ID AGE SEX NAME_SURENAME BIRTH_DATE</code></p>

<pre><code> NAME_SURENAME - not analyzed - this field is indexed for grouping purposes
 NAME, SURENAME - analyzed
</code></pre>

<p>The task is simple - search 5 unique workers sorted by birth_date (unique means the same name and surename, even if they are in different age and are different people) </p>

<p>I read about aggregation queries and as I understand, I can get only aggregations without documents. Unfortunatelly I aggregate by name and surename so I won't have other fields in results in buckets, like for example document ID field at least. But I also read about TopHit aggregation, that it returns document, and i tried it - the second idea below.</p>

<p>I have two ideas</p>

<p>1) Not use aggregations, just search 5 workers, filter duplicates in java and again search workers and filter duplicates in Java till I reach 5 unique results</p>

<p>2) Use aggregations. I event tried it like below, it even works on test data but since it is my first time, please advice, whether it works accidentially or it is done correctly? So generally I thought I could get 5 buckets with one TopHit document. I have no idea how TopHit document is chosen but it seems to work. Below is the code</p>

<pre><code>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&lt;Worker&gt; results = new ArrayList&lt;&gt;();
            for (Terms.Bucket bucket : aggregations.getBuckets()) {
                Optional&lt;Aggregation&gt; first = bucket.getAggregations().asList().stream().filter(aggregation -&gt; aggregation instanceof TopHits).findFirst();
                SearchHit searchHitFields = ((TopHits) first.get()).getHits().getHits()[0];

                Transformer&lt;SearchHit, Worker&gt; transformer = transformers.get(Worker.class);
                Worker transform = transformer.transform(searchHitFields);
                results.add(transform);
            }
            return results;//
</code></pre>