nested-aggregation.asciidoc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. [[search-aggregations-bucket-nested-aggregation]]
  2. === Nested aggregation
  3. ++++
  4. <titleabbrev>Nested</titleabbrev>
  5. ++++
  6. A special single bucket aggregation that enables aggregating nested documents.
  7. For example, lets say we have an index of products, and each product holds the list of resellers - each having its own
  8. price for the product. The mapping could look like:
  9. [source,console,id=nested-aggregation-example]
  10. ----
  11. PUT /products
  12. {
  13. "mappings": {
  14. "properties": {
  15. "resellers": { <1>
  16. "type": "nested",
  17. "properties": {
  18. "reseller": {
  19. "type": "keyword"
  20. },
  21. "price": {
  22. "type": "double"
  23. }
  24. }
  25. }
  26. }
  27. }
  28. }
  29. ----
  30. <1> `resellers` is an array that holds nested documents.
  31. The following request adds a product with two resellers:
  32. [source,console]
  33. ----
  34. PUT /products/_doc/0?refresh
  35. {
  36. "name": "LED TV", <1>
  37. "resellers": [
  38. {
  39. "reseller": "companyA",
  40. "price": 350
  41. },
  42. {
  43. "reseller": "companyB",
  44. "price": 500
  45. }
  46. ]
  47. }
  48. ----
  49. // TEST[continued]
  50. <1> We are using a dynamic mapping for the `name` attribute.
  51. The following request returns the minimum price a product can be purchased for:
  52. [source,console]
  53. ----
  54. GET /products/_search?size=0
  55. {
  56. "query": {
  57. "match": {
  58. "name": "led tv"
  59. }
  60. },
  61. "aggs": {
  62. "resellers": {
  63. "nested": {
  64. "path": "resellers"
  65. },
  66. "aggs": {
  67. "min_price": {
  68. "min": {
  69. "field": "resellers.price"
  70. }
  71. }
  72. }
  73. }
  74. }
  75. }
  76. ----
  77. // TEST[s/size=0/size=0&filter_path=aggregations/]
  78. // TEST[continued]
  79. As you can see above, the nested aggregation requires the `path` of the nested documents within the top level documents.
  80. Then one can define any type of aggregation over these nested documents.
  81. Response:
  82. [source,console-result]
  83. ----
  84. {
  85. ...
  86. "aggregations": {
  87. "resellers": {
  88. "doc_count": 2,
  89. "min_price": {
  90. "value": 350.0
  91. }
  92. }
  93. }
  94. }
  95. ----
  96. // TESTRESPONSE[s/\.\.\.//]
  97. You can use a <<search-aggregations-bucket-filter-aggregation,`filter`>>
  98. sub-aggregation to return results for a specific reseller.
  99. [source,console]
  100. ----
  101. GET /products/_search?size=0
  102. {
  103. "query": {
  104. "match": {
  105. "name": "led tv"
  106. }
  107. },
  108. "aggs": {
  109. "resellers": {
  110. "nested": {
  111. "path": "resellers"
  112. },
  113. "aggs": {
  114. "filter_reseller": {
  115. "filter": {
  116. "bool": {
  117. "filter": [
  118. {
  119. "term": {
  120. "resellers.reseller": "companyB"
  121. }
  122. }
  123. ]
  124. }
  125. },
  126. "aggs": {
  127. "min_price": {
  128. "min": {
  129. "field": "resellers.price"
  130. }
  131. }
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }
  138. ----
  139. // TEST[s/size=0/size=0&filter_path=aggregations/]
  140. // TEST[continued]
  141. The search returns:
  142. [source,console-result]
  143. ----
  144. {
  145. ...
  146. "aggregations": {
  147. "resellers": {
  148. "doc_count": 2,
  149. "filter_reseller": {
  150. "doc_count": 1,
  151. "min_price": {
  152. "value": 500.0
  153. }
  154. }
  155. }
  156. }
  157. }
  158. ----
  159. // TESTRESPONSE[s/\.\.\.//]