derivative-aggregation.asciidoc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. [[search-aggregations-pipeline-derivative-aggregation]]
  2. === Derivative aggregation
  3. ++++
  4. <titleabbrev>Derivative</titleabbrev>
  5. ++++
  6. A parent pipeline aggregation which calculates the derivative of a specified metric in a parent histogram (or date_histogram)
  7. aggregation. The specified metric must be numeric and the enclosing histogram must have `min_doc_count` set to `0` (default
  8. for `histogram` aggregations).
  9. ==== Syntax
  10. A `derivative` aggregation looks like this in isolation:
  11. [source,js]
  12. --------------------------------------------------
  13. "derivative": {
  14. "buckets_path": "the_sum"
  15. }
  16. --------------------------------------------------
  17. // NOTCONSOLE
  18. [[derivative-params]]
  19. .`derivative` Parameters
  20. [options="header"]
  21. |===
  22. |Parameter Name |Description |Required |Default Value
  23. |`buckets_path` |The path to the buckets we wish to find the derivative for (see <<buckets-path-syntax>> for more
  24. details) |Required |
  25. |`gap_policy` |The policy to apply when gaps are found in the data (see <<gap-policy>> for more
  26. details)|Optional |`skip`
  27. |`format` |{javadoc}/java.base/java/text/DecimalFormat.html[DecimalFormat pattern] for the
  28. output value. If specified, the formatted value is returned in the aggregation's
  29. `value_as_string` property |Optional | `null`
  30. |===
  31. ==== First Order Derivative
  32. The following snippet calculates the derivative of the total monthly `sales`:
  33. [source,console]
  34. --------------------------------------------------
  35. POST /sales/_search
  36. {
  37. "size": 0,
  38. "aggs": {
  39. "sales_per_month": {
  40. "date_histogram": {
  41. "field": "date",
  42. "calendar_interval": "month"
  43. },
  44. "aggs": {
  45. "sales": {
  46. "sum": {
  47. "field": "price"
  48. }
  49. },
  50. "sales_deriv": {
  51. "derivative": {
  52. "buckets_path": "sales" <1>
  53. }
  54. }
  55. }
  56. }
  57. }
  58. }
  59. --------------------------------------------------
  60. // TEST[setup:sales]
  61. <1> `buckets_path` instructs this derivative aggregation to use the output of the `sales` aggregation for the derivative
  62. And the following may be the response:
  63. [source,console-result]
  64. --------------------------------------------------
  65. {
  66. "took": 11,
  67. "timed_out": false,
  68. "_shards": ...,
  69. "hits": ...,
  70. "aggregations": {
  71. "sales_per_month": {
  72. "buckets": [
  73. {
  74. "key_as_string": "2015/01/01 00:00:00",
  75. "key": 1420070400000,
  76. "doc_count": 3,
  77. "sales": {
  78. "value": 550.0
  79. } <1>
  80. },
  81. {
  82. "key_as_string": "2015/02/01 00:00:00",
  83. "key": 1422748800000,
  84. "doc_count": 2,
  85. "sales": {
  86. "value": 60.0
  87. },
  88. "sales_deriv": {
  89. "value": -490.0 <2>
  90. }
  91. },
  92. {
  93. "key_as_string": "2015/03/01 00:00:00",
  94. "key": 1425168000000,
  95. "doc_count": 2, <3>
  96. "sales": {
  97. "value": 375.0
  98. },
  99. "sales_deriv": {
  100. "value": 315.0
  101. }
  102. }
  103. ]
  104. }
  105. }
  106. }
  107. --------------------------------------------------
  108. // TESTRESPONSE[s/"took": 11/"took": $body.took/]
  109. // TESTRESPONSE[s/"_shards": \.\.\./"_shards": $body._shards/]
  110. // TESTRESPONSE[s/"hits": \.\.\./"hits": $body.hits/]
  111. <1> No derivative for the first bucket since we need at least 2 data points to calculate the derivative
  112. <2> Derivative value units are implicitly defined by the `sales` aggregation and the parent histogram so in this case the units
  113. would be $/month assuming the `price` field has units of $.
  114. <3> The number of documents in the bucket are represented by the `doc_count`
  115. ==== Second Order Derivative
  116. A second order derivative can be calculated by chaining the derivative pipeline aggregation onto the result of another derivative
  117. pipeline aggregation as in the following example which will calculate both the first and the second order derivative of the total
  118. monthly sales:
  119. [source,console]
  120. --------------------------------------------------
  121. POST /sales/_search
  122. {
  123. "size": 0,
  124. "aggs": {
  125. "sales_per_month": {
  126. "date_histogram": {
  127. "field": "date",
  128. "calendar_interval": "month"
  129. },
  130. "aggs": {
  131. "sales": {
  132. "sum": {
  133. "field": "price"
  134. }
  135. },
  136. "sales_deriv": {
  137. "derivative": {
  138. "buckets_path": "sales"
  139. }
  140. },
  141. "sales_2nd_deriv": {
  142. "derivative": {
  143. "buckets_path": "sales_deriv" <1>
  144. }
  145. }
  146. }
  147. }
  148. }
  149. }
  150. --------------------------------------------------
  151. // TEST[setup:sales]
  152. <1> `buckets_path` for the second derivative points to the name of the first derivative
  153. And the following may be the response:
  154. [source,console-result]
  155. --------------------------------------------------
  156. {
  157. "took": 50,
  158. "timed_out": false,
  159. "_shards": ...,
  160. "hits": ...,
  161. "aggregations": {
  162. "sales_per_month": {
  163. "buckets": [
  164. {
  165. "key_as_string": "2015/01/01 00:00:00",
  166. "key": 1420070400000,
  167. "doc_count": 3,
  168. "sales": {
  169. "value": 550.0
  170. } <1>
  171. },
  172. {
  173. "key_as_string": "2015/02/01 00:00:00",
  174. "key": 1422748800000,
  175. "doc_count": 2,
  176. "sales": {
  177. "value": 60.0
  178. },
  179. "sales_deriv": {
  180. "value": -490.0
  181. } <1>
  182. },
  183. {
  184. "key_as_string": "2015/03/01 00:00:00",
  185. "key": 1425168000000,
  186. "doc_count": 2,
  187. "sales": {
  188. "value": 375.0
  189. },
  190. "sales_deriv": {
  191. "value": 315.0
  192. },
  193. "sales_2nd_deriv": {
  194. "value": 805.0
  195. }
  196. }
  197. ]
  198. }
  199. }
  200. }
  201. --------------------------------------------------
  202. // TESTRESPONSE[s/"took": 50/"took": $body.took/]
  203. // TESTRESPONSE[s/"_shards": \.\.\./"_shards": $body._shards/]
  204. // TESTRESPONSE[s/"hits": \.\.\./"hits": $body.hits/]
  205. <1> No second derivative for the first two buckets since we need at least 2 data points from the first derivative to calculate the
  206. second derivative
  207. ==== Units
  208. The derivative aggregation allows the units of the derivative values to be specified. This returns an extra field in the response
  209. `normalized_value` which reports the derivative value in the desired x-axis units. In the below example we calculate the derivative
  210. of the total sales per month but ask for the derivative of the sales as in the units of sales per day:
  211. [source,console]
  212. --------------------------------------------------
  213. POST /sales/_search
  214. {
  215. "size": 0,
  216. "aggs": {
  217. "sales_per_month": {
  218. "date_histogram": {
  219. "field": "date",
  220. "calendar_interval": "month"
  221. },
  222. "aggs": {
  223. "sales": {
  224. "sum": {
  225. "field": "price"
  226. }
  227. },
  228. "sales_deriv": {
  229. "derivative": {
  230. "buckets_path": "sales",
  231. "unit": "day" <1>
  232. }
  233. }
  234. }
  235. }
  236. }
  237. }
  238. --------------------------------------------------
  239. // TEST[setup:sales]
  240. <1> `unit` specifies what unit to use for the x-axis of the derivative calculation
  241. And the following may be the response:
  242. [source,console-result]
  243. --------------------------------------------------
  244. {
  245. "took": 50,
  246. "timed_out": false,
  247. "_shards": ...,
  248. "hits": ...,
  249. "aggregations": {
  250. "sales_per_month": {
  251. "buckets": [
  252. {
  253. "key_as_string": "2015/01/01 00:00:00",
  254. "key": 1420070400000,
  255. "doc_count": 3,
  256. "sales": {
  257. "value": 550.0
  258. } <1>
  259. },
  260. {
  261. "key_as_string": "2015/02/01 00:00:00",
  262. "key": 1422748800000,
  263. "doc_count": 2,
  264. "sales": {
  265. "value": 60.0
  266. },
  267. "sales_deriv": {
  268. "value": -490.0, <1>
  269. "normalized_value": -15.806451612903226 <2>
  270. }
  271. },
  272. {
  273. "key_as_string": "2015/03/01 00:00:00",
  274. "key": 1425168000000,
  275. "doc_count": 2,
  276. "sales": {
  277. "value": 375.0
  278. },
  279. "sales_deriv": {
  280. "value": 315.0,
  281. "normalized_value": 11.25
  282. }
  283. }
  284. ]
  285. }
  286. }
  287. }
  288. --------------------------------------------------
  289. // TESTRESPONSE[s/"took": 50/"took": $body.took/]
  290. // TESTRESPONSE[s/"_shards": \.\.\./"_shards": $body._shards/]
  291. // TESTRESPONSE[s/"hits": \.\.\./"hits": $body.hits/]
  292. <1> `value` is reported in the original units of 'per month'
  293. <2> `normalized_value` is reported in the desired units of 'per day'