| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 | [role="xpack"][testenv="basic"][[search-aggregations-metrics-top-metrics]]=== Top Metrics AggregationThe `top_metrics` aggregation selects metrics from the document with the largest or smallest "sort"value. For example, this gets the value of the `m` field on the document with the largest value of `s`:[source,console,id=search-aggregations-metrics-top-metrics-simple]----POST /test/_bulk?refresh{"index": {}}{"s": 1, "m": 3.1415}{"index": {}}{"s": 2, "m": 1.0}{"index": {}}{"s": 3, "m": 2.71828}POST /test/_search?filter_path=aggregations{  "aggs": {    "tm": {      "top_metrics": {        "metrics": {"field": "m"},        "sort": {"s": "desc"}      }    }  }}----Which returns:[source,js]----{  "aggregations": {    "tm": {      "top": [ {"sort": [3], "metrics": {"m": 2.718280076980591 } } ]    }  }}----// TESTRESPONSE`top_metrics` is fairly similar to <<search-aggregations-metrics-top-hits-aggregation, `top_hits`>>in spirit but because it is more limited it is able to do its job using less memory and is oftenfaster.==== `sort`The `sort` field in the metric request functions exactly the same as the `sort` field in the<<request-body-search-sort, search>> request except:* It can't be used on <<binary,binary>>, <<flattened,flattened>>, <<ip,ip>>,<<keyword,keyword>>, or <<text,text>> fields.* It only supports a single sort value so which document wins ties is not specified.The metrics that the aggregation returns is the first hit that would be returned by the searchrequest. So,`"sort": {"s": "desc"}`:: gets metrics from the document with the highest `s``"sort": {"s": "asc"}`:: gets the metrics from the document with the lowest `s``"sort": {"_geo_distance": {"location": "35.7796, -78.6382"}}`::  gets metrics from the documents with `location` *closest* to `35.7796, -78.6382``"sort": "_score"`:: gets metrics from the document with the highest score==== `metrics``metrics` selects the fields of the "top" document to return. You can requesta single metric with something like `"metric": {"field": "m"}` or multiplemetrics by requesting a list of metrics like `"metric": [{"field": "m"}, {"field": "i"}`.Here is a more complete example:[source,console,id=search-aggregations-metrics-top-metrics-list-of-metrics]----PUT /test{  "mappings": {    "properties": {      "d": {"type": "date"}    }  }}POST /test/_bulk?refresh{"index": {}}{"s": 1, "m": 3.1415, "i": 1, "d": "2020-01-01T00:12:12Z"}{"index": {}}{"s": 2, "m": 1.0, "i": 6, "d": "2020-01-02T00:12:12Z"}{"index": {}}{"s": 3, "m": 2.71828, "i": -12, "d": "2019-12-31T00:12:12Z"}POST /test/_search?filter_path=aggregations{  "aggs": {    "tm": {      "top_metrics": {        "metrics": [          {"field": "m"},          {"field": "i"},          {"field": "d"}        ],        "sort": {"s": "desc"}      }    }  }}----Which returns:[source,js]----{  "aggregations": {    "tm": {      "top": [ {        "sort": [3],        "metrics": {          "m": 2.718280076980591,          "i": -12,          "d": "2019-12-31T00:12:12.000Z"        }      } ]    }  }}----// TESTRESPONSE==== `size``top_metrics` can return the top few document's worth of metrics using the size parameter:[source,console,id=search-aggregations-metrics-top-metrics-size]----POST /test/_bulk?refresh{"index": {}}{"s": 1, "m": 3.1415}{"index": {}}{"s": 2, "m": 1.0}{"index": {}}{"s": 3, "m": 2.71828}POST /test/_search?filter_path=aggregations{  "aggs": {    "tm": {      "top_metrics": {        "metrics": {"field": "m"},        "sort": {"s": "desc"},        "size": 3      }    }  }}----Which returns:[source,js]----{  "aggregations": {    "tm": {      "top": [        {"sort": [3], "metrics": {"m": 2.718280076980591 } },        {"sort": [2], "metrics": {"m": 1.0 } },        {"sort": [1], "metrics": {"m": 3.1414999961853027 } }      ]    }  }}----// TESTRESPONSEThe default `size` is 1. The maximum default size is `10` because the aggregation'sworking storage is "dense", meaning we allocate `size` slots for every bucket. `10`is a *very* conservative default maximum and you can raise it if you need to bychanging the `top_metrics_max_size` index setting. But know that large sizes cantake a fair bit of memory, especially if they are inside of an aggregation whichmakes many buckes like a large<<search-aggregations-metrics-top-metrics-example-terms, terms aggregation>>. Ifyou till want to raise it, use something like:[source,console]----PUT /test/_settings{  "top_metrics_max_size": 100}----// TEST[continued]NOTE: If `size` is more than `1` the `top_metrics` aggregation can't be the *target* of a sort.==== Examples[[search-aggregations-metrics-top-metrics-example-terms]]===== Use with termsThis aggregation should be quite useful inside of <<search-aggregations-bucket-terms-aggregation, `terms`>>aggregation, to, say, find the last value reported by each server.[source,console,id=search-aggregations-metrics-top-metrics-terms]----PUT /node{  "mappings": {    "properties": {      "ip": {"type": "ip"},      "date": {"type": "date"}    }  }}POST /node/_bulk?refresh{"index": {}}{"ip": "192.168.0.1", "date": "2020-01-01T01:01:01", "m": 1}{"index": {}}{"ip": "192.168.0.1", "date": "2020-01-01T02:01:01", "m": 2}{"index": {}}{"ip": "192.168.0.2", "date": "2020-01-01T02:01:01", "m": 3}POST /node/_search?filter_path=aggregations{  "aggs": {    "ip": {      "terms": {        "field": "ip"      },      "aggs": {        "tm": {          "top_metrics": {            "metrics": {"field": "m"},            "sort": {"date": "desc"}          }        }      }    }  }}----Which returns:[source,js]----{  "aggregations": {    "ip": {      "buckets": [        {          "key": "192.168.0.1",          "doc_count": 2,          "tm": {            "top": [ {"sort": ["2020-01-01T02:01:01.000Z"], "metrics": {"m": 2 } } ]          }        },        {          "key": "192.168.0.2",          "doc_count": 1,          "tm": {            "top": [ {"sort": ["2020-01-01T02:01:01.000Z"], "metrics": {"m": 3 } } ]          }        }      ],      "doc_count_error_upper_bound": 0,      "sum_other_doc_count": 0    }  }}----// TESTRESPONSEUnlike `top_hits`, you can sort buckets by the results of this metric:[source,console]----POST /node/_search?filter_path=aggregations{  "aggs": {    "ip": {      "terms": {        "field": "ip",        "order": {"tm.m": "desc"}      },      "aggs": {        "tm": {          "top_metrics": {            "metrics": {"field": "m"},            "sort": {"date": "desc"}          }        }      }    }  }}----// TEST[continued]Which returns:[source,js]----{  "aggregations": {    "ip": {      "buckets": [        {          "key": "192.168.0.2",          "doc_count": 1,          "tm": {            "top": [ {"sort": ["2020-01-01T02:01:01.000Z"], "metrics": {"m": 3 } } ]          }        },        {          "key": "192.168.0.1",          "doc_count": 2,          "tm": {            "top": [ {"sort": ["2020-01-01T02:01:01.000Z"], "metrics": {"m": 2 } } ]          }        }      ],      "doc_count_error_upper_bound": 0,      "sum_other_doc_count": 0    }  }}----// TESTRESPONSE===== Mixed sort typesSorting `top_metrics` by a field that has different types across differentindices producs somewhat suprising results: floating point fields arealways sorted independantly of whole numbered fields.[source,console,id=search-aggregations-metrics-top-metrics-mixed-sort]----POST /test/_bulk?refresh{"index": {"_index": "test1"}}{"s": 1, "m": 3.1415}{"index": {"_index": "test1"}}{"s": 2, "m": 1}{"index": {"_index": "test2"}}{"s": 3.1, "m": 2.71828}POST /test*/_search?filter_path=aggregations{  "aggs": {    "tm": {      "top_metrics": {        "metrics": {"field": "m"},        "sort": {"s": "asc"}      }    }  }}----Which returns:[source,js]----{  "aggregations": {    "tm": {      "top": [ {"sort": [3.0999999046325684], "metrics": {"m": 2.718280076980591 } } ]    }  }}----// TESTRESPONSEWhile this is better than an error it *probably* isn't what you were going for.While it does lose some precision, you can explictly cast the whole numberfields to floating points with something like:[source,console]----POST /test*/_search?filter_path=aggregations{  "aggs": {    "tm": {      "top_metrics": {        "metrics": {"field": "m"},        "sort": {"s": {"order": "asc", "numeric_type": "double"}}      }    }  }}----// TEST[continued]Which returns the much more expected:[source,js]----{  "aggregations": {    "tm": {      "top": [ {"sort": [1.0], "metrics": {"m": 3.1414999961853027 } } ]    }  }}----// TESTRESPONSE
 |