Top hits aggregation #
Keeps track of the most relevant documents being aggregated — useful
inside a bucket aggregation (e.g. terms) to return the best-matching
documents per bucket. Where most metric aggs reduce a bucket to one
number, top_hits keeps the documents themselves.
How it works #
top_hits runs over a bucket’s document set and returns up to size
documents in a hits envelope: hits.total — a plain count
of the bucket’s documents — and hits.hits[], each entry carrying
_id (the engine’s internal numeric document id) and _source.
- Sort leniency. The
sortbody accepts every spelling — a bare string ("amount"), an array of strings or objects, or a single{"field": "order"}object — and normalizes them all to an object array; a bare field name meansasc. - Flat buckets. The column-store fast path and the executor path
both walk the bucket’s candidate documents and fetch each stored
source. In the current engine the hits come back in index order: the
normalized
sortis not yet applied to flat-bucket ranking. - Nested buckets sort for real. Under a
nestedaggregation,top_hitsis element-level: each hit is one stored element of the nested path, identified by_nested: {field, offset}, and the elements are sorted per the sort spec — numeric when both sides parse as numbers, lexicographic otherwise, missing values sorting last underasc. _source.true/false/ a list of fields all parse; the current implementation returns the full stored source either way.- Fan-out. Shard hit lists are concatenated and truncated back to
sizeat the coordinator. - Request knobs such as
fromare not parsed and are ignored.
Examples #
Top 3 sales per merchant:
POST /sales/_search
{
"aggs": {
"top_merchants": {
"terms": { "field": "merchant" },
"aggs": {
"top_sales": {
"top_hits": {
"size": 3,
"sort": [{ "field": "amount", "order": "desc" }]
}
}
}
}
}
}
Inside each terms bucket hits.total is the bucket’s document count
(30 per merchant on the teaching dataset), and the entries are the
bucket’s leading documents in index order.
Use cases #
- Top-N rows per group — the classic shape:
termson merchant or category with a smalltop_hitsinside, so one request returns the group counts and a few representative rows per group. - A representative product per category —
terms(category)over the 30 products withtop_hits: {size: 1}yields one exemplar row per category for a listing page. - Nested element extraction — under
nested, surface stored child elements (a product’svariants, an order’s line items) ranked by an element field. - Bucket debugging — when a bucket’s count surprises you, attach
top_hitsand read the documents that actually fell into it. - Facet previews — “show me the documents behind this facet value” without issuing a second search per value.
Parameters for top_hits
#
size
(Optional, integer, default:3) Number of top hits to return per bucket.sort
(Optional) Sort order for the top hits. Accepts"field",["a", "b"]and[{ "field": "asc" }]forms — all normalize to an object array._source
(Optional)true,false, or a list of fields to include. The full stored source is returned either way.
Related #
top_metrics— when one field value from the top document is enough and whole documents are too heavy.terms— the bucket aggregationtop_hitsusually lives in.nested— element-level top hits with real sorting.