rollup-search.asciidoc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. [role="xpack"]
  2. [[rollup-search]]
  3. === Rollup Search
  4. ++++
  5. <titleabbrev>Rollup Search</titleabbrev>
  6. ++++
  7. experimental[]
  8. The Rollup Search endpoint allows searching rolled-up data using the standard query DSL. The Rollup Search endpoint
  9. is needed because, internally, rolled-up documents utilize a different document structure than the original data. The
  10. Rollup Search endpoint rewrites standard query DSL into a format that matches the rollup documents, then takes the response
  11. and rewrites it back to what a client would expect given the original query.
  12. ==== Request
  13. `GET {index}/_rollup_search`
  14. //===== Description
  15. ==== Path Parameters
  16. `index`::
  17. (string) Index, indices or index-pattern to execute a rollup search against. This can include both rollup and non-rollup
  18. indices.
  19. Rules for the `index` parameter:
  20. - At least one index/index-pattern must be specified. This can be either a rollup or non-rollup index. Omitting the index parameter,
  21. or using `_all`, is not permitted
  22. - Multiple non-rollup indices may be specified
  23. - Only one rollup index may be specified. If more than one are supplied an exception will be thrown
  24. ==== Request Body
  25. The request body supports a subset of features from the regular Search API. It supports:
  26. - `query` param for specifying an DSL query, subject to some limitations (see <<rollup-search-limitations>> and <<rollup-agg-limitations>>
  27. - `aggregations` param for specifying aggregations
  28. Functionality that is not available:
  29. - `size`: because rollups work on pre-aggregated data, no search hits can be returned and so size must be set to zero or
  30. omitted entirely.
  31. - `highlighter`, `suggestors`, `post_filter`, `profile`, `explain` are similarly disallowed
  32. ==== Historical-only search example
  33. Imagine we have an index named `sensor-1` full of raw data, and we have created a rollup job with the following configuration:
  34. [source,js]
  35. --------------------------------------------------
  36. PUT _xpack/rollup/job/sensor
  37. {
  38. "index_pattern": "sensor-*",
  39. "rollup_index": "sensor_rollup",
  40. "cron": "*/30 * * * * ?",
  41. "page_size" :1000,
  42. "groups" : {
  43. "date_histogram": {
  44. "field": "timestamp",
  45. "interval": "1h",
  46. "delay": "7d"
  47. },
  48. "terms": {
  49. "fields": ["node"]
  50. }
  51. },
  52. "metrics": [
  53. {
  54. "field": "temperature",
  55. "metrics": ["min", "max", "sum"]
  56. },
  57. {
  58. "field": "voltage",
  59. "metrics": ["avg"]
  60. }
  61. ]
  62. }
  63. --------------------------------------------------
  64. // CONSOLE
  65. // TEST[setup:sensor_index]
  66. This rolls up the `sensor-*` pattern and stores the results in `sensor_rollup`. To search this rolled up data, we
  67. need to use the `_rollup_search` endpoint. However, you'll notice that we can use regular query DSL to search the
  68. rolled-up data:
  69. [source,js]
  70. --------------------------------------------------
  71. GET /sensor_rollup/_rollup_search
  72. {
  73. "size": 0,
  74. "aggregations": {
  75. "max_temperature": {
  76. "max": {
  77. "field": "temperature"
  78. }
  79. }
  80. }
  81. }
  82. --------------------------------------------------
  83. // CONSOLE
  84. // TEST[setup:sensor_prefab_data]
  85. // TEST[s/_rollup_search/_rollup_search?filter_path=took,timed_out,terminated_early,_shards,hits,aggregations/]
  86. The query is targeting the `sensor_rollup` data, since this contains the rollup data as configured in the job. A `max`
  87. aggregation has been used on the `temperature` field, yielding the following response:
  88. [source,js]
  89. ----
  90. {
  91. "took" : 102,
  92. "timed_out" : false,
  93. "terminated_early" : false,
  94. "_shards" : ... ,
  95. "hits" : {
  96. "total" : 0,
  97. "max_score" : 0.0,
  98. "hits" : [ ]
  99. },
  100. "aggregations" : {
  101. "max_temperature" : {
  102. "value" : 202.0
  103. }
  104. }
  105. }
  106. ----
  107. // TESTRESPONSE[s/"took" : 102/"took" : $body.$_path/]
  108. // TESTRESPONSE[s/"_shards" : \.\.\. /"_shards" : $body.$_path/]
  109. The response is exactly as you'd expect from a regular query + aggregation; it provides some metadata about the request
  110. (`took`, `_shards`, etc), the search hits (which is always empty for rollup searches), and the aggregation response.
  111. Rollup searches are limited to functionality that was configured in the rollup job. For example, we are not able to calculate
  112. the average temperature because `avg` was not one of the configured metrics for the `temperature` field. If we try
  113. to execute that search:
  114. [source,js]
  115. --------------------------------------------------
  116. GET sensor_rollup/_rollup_search
  117. {
  118. "size": 0,
  119. "aggregations": {
  120. "avg_temperature": {
  121. "avg": {
  122. "field": "temperature"
  123. }
  124. }
  125. }
  126. }
  127. --------------------------------------------------
  128. // CONSOLE
  129. // TEST[continued]
  130. // TEST[catch:/illegal_argument_exception/]
  131. [source,js]
  132. ----
  133. {
  134. "error" : {
  135. "root_cause" : [
  136. {
  137. "type" : "illegal_argument_exception",
  138. "reason" : "There is not a rollup job that has a [avg] agg with name [avg_temperature] which also satisfies all requirements of query.",
  139. "stack_trace": ...
  140. }
  141. ],
  142. "type" : "illegal_argument_exception",
  143. "reason" : "There is not a rollup job that has a [avg] agg with name [avg_temperature] which also satisfies all requirements of query.",
  144. "stack_trace": ...
  145. },
  146. "status": 400
  147. }
  148. ----
  149. // TESTRESPONSE[s/"stack_trace": \.\.\./"stack_trace": $body.$_path/]
  150. ==== Searching both historical rollup and non-rollup data
  151. The Rollup Search API has the capability to search across both "live", non-rollup data as well as the aggregated rollup
  152. data. This is done by simply adding the live indices to the URI:
  153. [source,js]
  154. --------------------------------------------------
  155. GET sensor-1,sensor_rollup/_rollup_search <1>
  156. {
  157. "size": 0,
  158. "aggregations": {
  159. "max_temperature": {
  160. "max": {
  161. "field": "temperature"
  162. }
  163. }
  164. }
  165. }
  166. --------------------------------------------------
  167. // CONSOLE
  168. // TEST[continued]
  169. // TEST[s/_rollup_search/_rollup_search?filter_path=took,timed_out,terminated_early,_shards,hits,aggregations/]
  170. <1> Note the URI now searches `sensor-1` and `sensor_rollup` at the same time
  171. When the search is executed, the Rollup Search endpoint will do two things:
  172. 1. The original request will be sent to the non-rollup index unaltered
  173. 2. A rewritten version of the original request will be sent to the rollup index.
  174. When the two responses are received, the endpoint will then rewrite the rollup response and merge the two together.
  175. During the merging process, if there is any overlap in buckets between the two responses, the buckets from the non-rollup
  176. index will be used.
  177. The response to the above query will look as expected, despite spanning rollup and non-rollup indices:
  178. [source,js]
  179. ----
  180. {
  181. "took" : 102,
  182. "timed_out" : false,
  183. "terminated_early" : false,
  184. "_shards" : ... ,
  185. "hits" : {
  186. "total" : 0,
  187. "max_score" : 0.0,
  188. "hits" : [ ]
  189. },
  190. "aggregations" : {
  191. "max_temperature" : {
  192. "value" : 202.0
  193. }
  194. }
  195. }
  196. ----
  197. // TESTRESPONSE[s/"took" : 102/"took" : $body.$_path/]
  198. // TESTRESPONSE[s/"_shards" : \.\.\. /"_shards" : $body.$_path/]