top-metrics-aggregation.asciidoc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. [role="xpack"]
  2. [testenv="basic"]
  3. [[search-aggregations-metrics-top-metrics]]
  4. === Top Metrics Aggregation
  5. The `top_metrics` aggregation selects metrics from the document with the largest or smallest "sort"
  6. value. For example, this gets the value of the `m` field on the document with the largest value of `s`:
  7. [source,console,id=search-aggregations-metrics-top-metrics-simple]
  8. ----
  9. POST /test/_bulk?refresh
  10. {"index": {}}
  11. {"s": 1, "m": 3.1415}
  12. {"index": {}}
  13. {"s": 2, "m": 1.0}
  14. {"index": {}}
  15. {"s": 3, "m": 2.71828}
  16. POST /test/_search?filter_path=aggregations
  17. {
  18. "aggs": {
  19. "tm": {
  20. "top_metrics": {
  21. "metrics": {"field": "m"},
  22. "sort": {"s": "desc"}
  23. }
  24. }
  25. }
  26. }
  27. ----
  28. Which returns:
  29. [source,js]
  30. ----
  31. {
  32. "aggregations": {
  33. "tm": {
  34. "top": [ {"sort": [3], "metrics": {"m": 2.718280076980591 } } ]
  35. }
  36. }
  37. }
  38. ----
  39. // TESTRESPONSE
  40. `top_metrics` is fairly similar to <<search-aggregations-metrics-top-hits-aggregation, `top_hits`>>
  41. in spirit but because it is more limited it is able to do its job using less memory and is often
  42. faster.
  43. ==== `sort`
  44. The `sort` field in the metric request functions exactly the same as the `sort` field in the
  45. <<sort-search-results, search>> request except:
  46. * It can't be used on <<binary,binary>>, <<flattened,flattened>>, <<ip,ip>>,
  47. <<keyword,keyword>>, or <<text,text>> fields.
  48. * It only supports a single sort value so which document wins ties is not specified.
  49. The metrics that the aggregation returns is the first hit that would be returned by the search
  50. request. So,
  51. `"sort": {"s": "desc"}`:: gets metrics from the document with the highest `s`
  52. `"sort": {"s": "asc"}`:: gets the metrics from the document with the lowest `s`
  53. `"sort": {"_geo_distance": {"location": "35.7796, -78.6382"}}`::
  54. gets metrics from the documents with `location` *closest* to `35.7796, -78.6382`
  55. `"sort": "_score"`:: gets metrics from the document with the highest score
  56. ==== `metrics`
  57. `metrics` selects the fields of the "top" document to return. You can request
  58. a single metric with something like `"metric": {"field": "m"}` or multiple
  59. metrics by requesting a list of metrics like `"metric": [{"field": "m"}, {"field": "i"}`.
  60. Here is a more complete example:
  61. [source,console,id=search-aggregations-metrics-top-metrics-list-of-metrics]
  62. ----
  63. PUT /test
  64. {
  65. "mappings": {
  66. "properties": {
  67. "d": {"type": "date"}
  68. }
  69. }
  70. }
  71. POST /test/_bulk?refresh
  72. {"index": {}}
  73. {"s": 1, "m": 3.1415, "i": 1, "d": "2020-01-01T00:12:12Z"}
  74. {"index": {}}
  75. {"s": 2, "m": 1.0, "i": 6, "d": "2020-01-02T00:12:12Z"}
  76. {"index": {}}
  77. {"s": 3, "m": 2.71828, "i": -12, "d": "2019-12-31T00:12:12Z"}
  78. POST /test/_search?filter_path=aggregations
  79. {
  80. "aggs": {
  81. "tm": {
  82. "top_metrics": {
  83. "metrics": [
  84. {"field": "m"},
  85. {"field": "i"},
  86. {"field": "d"}
  87. ],
  88. "sort": {"s": "desc"}
  89. }
  90. }
  91. }
  92. }
  93. ----
  94. Which returns:
  95. [source,js]
  96. ----
  97. {
  98. "aggregations": {
  99. "tm": {
  100. "top": [ {
  101. "sort": [3],
  102. "metrics": {
  103. "m": 2.718280076980591,
  104. "i": -12,
  105. "d": "2019-12-31T00:12:12.000Z"
  106. }
  107. } ]
  108. }
  109. }
  110. }
  111. ----
  112. // TESTRESPONSE
  113. ==== `size`
  114. `top_metrics` can return the top few document's worth of metrics using the size parameter:
  115. [source,console,id=search-aggregations-metrics-top-metrics-size]
  116. ----
  117. POST /test/_bulk?refresh
  118. {"index": {}}
  119. {"s": 1, "m": 3.1415}
  120. {"index": {}}
  121. {"s": 2, "m": 1.0}
  122. {"index": {}}
  123. {"s": 3, "m": 2.71828}
  124. POST /test/_search?filter_path=aggregations
  125. {
  126. "aggs": {
  127. "tm": {
  128. "top_metrics": {
  129. "metrics": {"field": "m"},
  130. "sort": {"s": "desc"},
  131. "size": 3
  132. }
  133. }
  134. }
  135. }
  136. ----
  137. Which returns:
  138. [source,js]
  139. ----
  140. {
  141. "aggregations": {
  142. "tm": {
  143. "top": [
  144. {"sort": [3], "metrics": {"m": 2.718280076980591 } },
  145. {"sort": [2], "metrics": {"m": 1.0 } },
  146. {"sort": [1], "metrics": {"m": 3.1414999961853027 } }
  147. ]
  148. }
  149. }
  150. }
  151. ----
  152. // TESTRESPONSE
  153. The default `size` is 1. The maximum default size is `10` because the aggregation's
  154. working storage is "dense", meaning we allocate `size` slots for every bucket. `10`
  155. is a *very* conservative default maximum and you can raise it if you need to by
  156. changing the `top_metrics_max_size` index setting. But know that large sizes can
  157. take a fair bit of memory, especially if they are inside of an aggregation which
  158. makes many buckes like a large
  159. <<search-aggregations-metrics-top-metrics-example-terms, terms aggregation>>. If
  160. you till want to raise it, use something like:
  161. [source,console]
  162. ----
  163. PUT /test/_settings
  164. {
  165. "top_metrics_max_size": 100
  166. }
  167. ----
  168. // TEST[continued]
  169. NOTE: If `size` is more than `1` the `top_metrics` aggregation can't be the *target* of a sort.
  170. ==== Examples
  171. [[search-aggregations-metrics-top-metrics-example-terms]]
  172. ===== Use with terms
  173. This aggregation should be quite useful inside of <<search-aggregations-bucket-terms-aggregation, `terms`>>
  174. aggregation, to, say, find the last value reported by each server.
  175. [source,console,id=search-aggregations-metrics-top-metrics-terms]
  176. ----
  177. PUT /node
  178. {
  179. "mappings": {
  180. "properties": {
  181. "ip": {"type": "ip"},
  182. "date": {"type": "date"}
  183. }
  184. }
  185. }
  186. POST /node/_bulk?refresh
  187. {"index": {}}
  188. {"ip": "192.168.0.1", "date": "2020-01-01T01:01:01", "m": 1}
  189. {"index": {}}
  190. {"ip": "192.168.0.1", "date": "2020-01-01T02:01:01", "m": 2}
  191. {"index": {}}
  192. {"ip": "192.168.0.2", "date": "2020-01-01T02:01:01", "m": 3}
  193. POST /node/_search?filter_path=aggregations
  194. {
  195. "aggs": {
  196. "ip": {
  197. "terms": {
  198. "field": "ip"
  199. },
  200. "aggs": {
  201. "tm": {
  202. "top_metrics": {
  203. "metrics": {"field": "m"},
  204. "sort": {"date": "desc"}
  205. }
  206. }
  207. }
  208. }
  209. }
  210. }
  211. ----
  212. Which returns:
  213. [source,js]
  214. ----
  215. {
  216. "aggregations": {
  217. "ip": {
  218. "buckets": [
  219. {
  220. "key": "192.168.0.1",
  221. "doc_count": 2,
  222. "tm": {
  223. "top": [ {"sort": ["2020-01-01T02:01:01.000Z"], "metrics": {"m": 2 } } ]
  224. }
  225. },
  226. {
  227. "key": "192.168.0.2",
  228. "doc_count": 1,
  229. "tm": {
  230. "top": [ {"sort": ["2020-01-01T02:01:01.000Z"], "metrics": {"m": 3 } } ]
  231. }
  232. }
  233. ],
  234. "doc_count_error_upper_bound": 0,
  235. "sum_other_doc_count": 0
  236. }
  237. }
  238. }
  239. ----
  240. // TESTRESPONSE
  241. Unlike `top_hits`, you can sort buckets by the results of this metric:
  242. [source,console]
  243. ----
  244. POST /node/_search?filter_path=aggregations
  245. {
  246. "aggs": {
  247. "ip": {
  248. "terms": {
  249. "field": "ip",
  250. "order": {"tm.m": "desc"}
  251. },
  252. "aggs": {
  253. "tm": {
  254. "top_metrics": {
  255. "metrics": {"field": "m"},
  256. "sort": {"date": "desc"}
  257. }
  258. }
  259. }
  260. }
  261. }
  262. }
  263. ----
  264. // TEST[continued]
  265. Which returns:
  266. [source,js]
  267. ----
  268. {
  269. "aggregations": {
  270. "ip": {
  271. "buckets": [
  272. {
  273. "key": "192.168.0.2",
  274. "doc_count": 1,
  275. "tm": {
  276. "top": [ {"sort": ["2020-01-01T02:01:01.000Z"], "metrics": {"m": 3 } } ]
  277. }
  278. },
  279. {
  280. "key": "192.168.0.1",
  281. "doc_count": 2,
  282. "tm": {
  283. "top": [ {"sort": ["2020-01-01T02:01:01.000Z"], "metrics": {"m": 2 } } ]
  284. }
  285. }
  286. ],
  287. "doc_count_error_upper_bound": 0,
  288. "sum_other_doc_count": 0
  289. }
  290. }
  291. }
  292. ----
  293. // TESTRESPONSE
  294. ===== Mixed sort types
  295. Sorting `top_metrics` by a field that has different types across different
  296. indices producs somewhat suprising results: floating point fields are
  297. always sorted independantly of whole numbered fields.
  298. [source,console,id=search-aggregations-metrics-top-metrics-mixed-sort]
  299. ----
  300. POST /test/_bulk?refresh
  301. {"index": {"_index": "test1"}}
  302. {"s": 1, "m": 3.1415}
  303. {"index": {"_index": "test1"}}
  304. {"s": 2, "m": 1}
  305. {"index": {"_index": "test2"}}
  306. {"s": 3.1, "m": 2.71828}
  307. POST /test*/_search?filter_path=aggregations
  308. {
  309. "aggs": {
  310. "tm": {
  311. "top_metrics": {
  312. "metrics": {"field": "m"},
  313. "sort": {"s": "asc"}
  314. }
  315. }
  316. }
  317. }
  318. ----
  319. Which returns:
  320. [source,js]
  321. ----
  322. {
  323. "aggregations": {
  324. "tm": {
  325. "top": [ {"sort": [3.0999999046325684], "metrics": {"m": 2.718280076980591 } } ]
  326. }
  327. }
  328. }
  329. ----
  330. // TESTRESPONSE
  331. While this is better than an error it *probably* isn't what you were going for.
  332. While it does lose some precision, you can explictly cast the whole number
  333. fields to floating points with something like:
  334. [source,console]
  335. ----
  336. POST /test*/_search?filter_path=aggregations
  337. {
  338. "aggs": {
  339. "tm": {
  340. "top_metrics": {
  341. "metrics": {"field": "m"},
  342. "sort": {"s": {"order": "asc", "numeric_type": "double"}}
  343. }
  344. }
  345. }
  346. }
  347. ----
  348. // TEST[continued]
  349. Which returns the much more expected:
  350. [source,js]
  351. ----
  352. {
  353. "aggregations": {
  354. "tm": {
  355. "top": [ {"sort": [1.0], "metrics": {"m": 3.1414999961853027 } } ]
  356. }
  357. }
  358. }
  359. ----
  360. // TESTRESPONSE