percentile-rank-aggregation.asciidoc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. [[search-aggregations-metrics-percentile-rank-aggregation]]
  2. === Percentile Ranks Aggregation
  3. A `multi-value` metrics aggregation that calculates one or more percentile ranks
  4. over numeric values extracted from the aggregated documents. These values
  5. can be extracted either from specific numeric fields in the documents, or
  6. be generated by a provided script.
  7. [NOTE]
  8. ==================================================
  9. Please see <<search-aggregations-metrics-percentile-aggregation-approximation>>
  10. and <<search-aggregations-metrics-percentile-aggregation-compression>> for advice
  11. regarding approximation and memory use of the percentile ranks aggregation
  12. ==================================================
  13. Percentile rank show the percentage of observed values which are below certain
  14. value. For example, if a value is greater than or equal to 95% of the observed values
  15. it is said to be at the 95th percentile rank.
  16. Assume your data consists of website load times. You may have a service agreement that
  17. 95% of page loads completely within 15ms and 99% of page loads complete within 30ms.
  18. Let's look at a range of percentiles representing load time:
  19. [source,js]
  20. --------------------------------------------------
  21. {
  22. "aggs" : {
  23. "load_time_outlier" : {
  24. "percentile_ranks" : {
  25. "field" : "load_time", <1>
  26. "values" : [15, 30]
  27. }
  28. }
  29. }
  30. }
  31. --------------------------------------------------
  32. <1> The field `load_time` must be a numeric field
  33. The response will look like this:
  34. [source,js]
  35. --------------------------------------------------
  36. {
  37. ...
  38. "aggregations": {
  39. "load_time_outlier": {
  40. "values" : {
  41. "15": 92,
  42. "30": 100
  43. }
  44. }
  45. }
  46. }
  47. --------------------------------------------------
  48. From this information you can determine you are hitting the 99% load time target but not quite
  49. hitting the 95% load time target
  50. ==== Keyed Response
  51. By default the `keyed` flag is set to `true` associates a unique string key with each bucket and returns the ranges as a hash rather than an array. Setting the `keyed` flag to `false` will disable this behavior:
  52. [source,js]
  53. --------------------------------------------------
  54. POST bank/account/_search?size=0
  55. {
  56. "aggs": {
  57. "balance_outlier": {
  58. "percentile_ranks": {
  59. "field": "balance",
  60. "values": [25000, 50000],
  61. "keyed": false
  62. }
  63. }
  64. }
  65. }
  66. --------------------------------------------------
  67. // CONSOLE
  68. // TEST[setup:bank]
  69. Response:
  70. [source,js]
  71. --------------------------------------------------
  72. {
  73. ...
  74. "aggregations": {
  75. "balance_outlier": {
  76. "values": [
  77. {
  78. "key": 25000.0,
  79. "value": 48.537724935732655
  80. },
  81. {
  82. "key": 50000.0,
  83. "value": 99.85567010309278
  84. }
  85. ]
  86. }
  87. }
  88. }
  89. --------------------------------------------------
  90. // TESTRESPONSE[s/\.\.\./"took": $body.took,"timed_out": false,"_shards": $body._shards,"hits": $body.hits,/]
  91. // TESTRESPONSE[s/48.537724935732655/$body.aggregations.balance_outlier.values.0.value/]
  92. // TESTRESPONSE[s/99.85567010309278/$body.aggregations.balance_outlier.values.1.value/]
  93. ==== Script
  94. The percentile rank metric supports scripting. For example, if our load times
  95. are in milliseconds but we want to specify values in seconds, we could use
  96. a script to convert them on-the-fly:
  97. [source,js]
  98. --------------------------------------------------
  99. {
  100. "aggs" : {
  101. "load_time_outlier" : {
  102. "percentile_ranks" : {
  103. "values" : [3, 5],
  104. "script" : {
  105. "lang": "painless",
  106. "inline": "doc['load_time'].value / params.timeUnit", <1>
  107. "params" : {
  108. "timeUnit" : 1000 <2>
  109. }
  110. }
  111. }
  112. }
  113. }
  114. }
  115. --------------------------------------------------
  116. <1> The `field` parameter is replaced with a `script` parameter, which uses the
  117. script to generate values which percentile ranks are calculated on
  118. <2> Scripting supports parameterized input just like any other script
  119. This will interpret the `script` parameter as an `inline` script with the `painless` script language and no script parameters. To use a file script use the following syntax:
  120. [source,js]
  121. --------------------------------------------------
  122. {
  123. "aggs" : {
  124. "load_time_outlier" : {
  125. "percentile_ranks" : {
  126. "values" : [3, 5],
  127. "script" : {
  128. "file": "my_script",
  129. "params" : {
  130. "timeUnit" : 1000
  131. }
  132. }
  133. }
  134. }
  135. }
  136. }
  137. --------------------------------------------------
  138. TIP: for indexed scripts replace the `file` parameter with an `id` parameter.
  139. ==== HDR Histogram
  140. experimental[]
  141. https://github.com/HdrHistogram/HdrHistogram[HDR Histogram] (High Dynamic Range Histogram) is an alternative implementation
  142. that can be useful when calculating percentile ranks for latency measurements as it can be faster than the t-digest implementation
  143. with the trade-off of a larger memory footprint. This implementation maintains a fixed worse-case percentage error (specified as a
  144. number of significant digits). This means that if data is recorded with values from 1 microsecond up to 1 hour (3,600,000,000
  145. microseconds) in a histogram set to 3 significant digits, it will maintain a value resolution of 1 microsecond for values up to
  146. 1 millisecond and 3.6 seconds (or better) for the maximum tracked value (1 hour).
  147. The HDR Histogram can be used by specifying the `method` parameter in the request:
  148. [source,js]
  149. --------------------------------------------------
  150. {
  151. "aggs" : {
  152. "load_time_outlier" : {
  153. "percentile_ranks" : {
  154. "field" : "load_time",
  155. "values" : [15, 30],
  156. "hdr": { <1>
  157. "number_of_significant_value_digits" : 3 <2>
  158. }
  159. }
  160. }
  161. }
  162. }
  163. --------------------------------------------------
  164. <1> `hdr` object indicates that HDR Histogram should be used to calculate the percentiles and specific settings for this algorithm can be specified inside the object
  165. <2> `number_of_significant_value_digits` specifies the resolution of values for the histogram in number of significant digits
  166. The HDRHistogram only supports positive values and will error if it is passed a negative value. It is also not a good idea to use
  167. the HDRHistogram if the range of values is unknown as this could lead to high memory usage.
  168. ==== Missing value
  169. The `missing` parameter defines how documents that are missing a value should be treated.
  170. By default they will be ignored but it is also possible to treat them as if they
  171. had a value.
  172. [source,js]
  173. --------------------------------------------------
  174. {
  175. "aggs" : {
  176. "grade_ranks" : {
  177. "percentile_ranks" : {
  178. "field" : "grade",
  179. "missing": 10 <1>
  180. }
  181. }
  182. }
  183. }
  184. --------------------------------------------------
  185. <1> Documents without a value in the `grade` field will fall into the same bucket as documents that have the value `10`.