search_aggs_bucket_histogram.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Copyright 2012-present Oliver Eilhard. All rights reserved.
  2. // Use of this source code is governed by a MIT-license.
  3. // See http://olivere.mit-license.org/license.txt for details.
  4. package elastic
  5. // HistogramAggregation is a multi-bucket values source based aggregation
  6. // that can be applied on numeric values extracted from the documents.
  7. // It dynamically builds fixed size (a.k.a. interval) buckets over the
  8. // values.
  9. // See: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-aggregations-bucket-histogram-aggregation.html
  10. type HistogramAggregation struct {
  11. field string
  12. script *Script
  13. missing interface{}
  14. subAggregations map[string]Aggregation
  15. meta map[string]interface{}
  16. interval float64
  17. order string
  18. orderAsc bool
  19. minDocCount *int64
  20. minBounds *float64
  21. maxBounds *float64
  22. offset *float64
  23. }
  24. func NewHistogramAggregation() *HistogramAggregation {
  25. return &HistogramAggregation{
  26. subAggregations: make(map[string]Aggregation),
  27. }
  28. }
  29. func (a *HistogramAggregation) Field(field string) *HistogramAggregation {
  30. a.field = field
  31. return a
  32. }
  33. func (a *HistogramAggregation) Script(script *Script) *HistogramAggregation {
  34. a.script = script
  35. return a
  36. }
  37. // Missing configures the value to use when documents miss a value.
  38. func (a *HistogramAggregation) Missing(missing interface{}) *HistogramAggregation {
  39. a.missing = missing
  40. return a
  41. }
  42. func (a *HistogramAggregation) SubAggregation(name string, subAggregation Aggregation) *HistogramAggregation {
  43. a.subAggregations[name] = subAggregation
  44. return a
  45. }
  46. // Meta sets the meta data to be included in the aggregation response.
  47. func (a *HistogramAggregation) Meta(metaData map[string]interface{}) *HistogramAggregation {
  48. a.meta = metaData
  49. return a
  50. }
  51. // Interval for this builder, must be greater than 0.
  52. func (a *HistogramAggregation) Interval(interval float64) *HistogramAggregation {
  53. a.interval = interval
  54. return a
  55. }
  56. // Order specifies the sort order. Valid values for order are:
  57. // "_key", "_count", a sub-aggregation name, or a sub-aggregation name
  58. // with a metric.
  59. func (a *HistogramAggregation) Order(order string, asc bool) *HistogramAggregation {
  60. a.order = order
  61. a.orderAsc = asc
  62. return a
  63. }
  64. func (a *HistogramAggregation) OrderByCount(asc bool) *HistogramAggregation {
  65. // "order" : { "_count" : "asc" }
  66. a.order = "_count"
  67. a.orderAsc = asc
  68. return a
  69. }
  70. func (a *HistogramAggregation) OrderByCountAsc() *HistogramAggregation {
  71. return a.OrderByCount(true)
  72. }
  73. func (a *HistogramAggregation) OrderByCountDesc() *HistogramAggregation {
  74. return a.OrderByCount(false)
  75. }
  76. func (a *HistogramAggregation) OrderByKey(asc bool) *HistogramAggregation {
  77. // "order" : { "_key" : "asc" }
  78. a.order = "_key"
  79. a.orderAsc = asc
  80. return a
  81. }
  82. func (a *HistogramAggregation) OrderByKeyAsc() *HistogramAggregation {
  83. return a.OrderByKey(true)
  84. }
  85. func (a *HistogramAggregation) OrderByKeyDesc() *HistogramAggregation {
  86. return a.OrderByKey(false)
  87. }
  88. // OrderByAggregation creates a bucket ordering strategy which sorts buckets
  89. // based on a single-valued calc get.
  90. func (a *HistogramAggregation) OrderByAggregation(aggName string, asc bool) *HistogramAggregation {
  91. // {
  92. // "aggs" : {
  93. // "genders" : {
  94. // "terms" : {
  95. // "field" : "gender",
  96. // "order" : { "avg_height" : "desc" }
  97. // },
  98. // "aggs" : {
  99. // "avg_height" : { "avg" : { "field" : "height" } }
  100. // }
  101. // }
  102. // }
  103. // }
  104. a.order = aggName
  105. a.orderAsc = asc
  106. return a
  107. }
  108. // OrderByAggregationAndMetric creates a bucket ordering strategy which
  109. // sorts buckets based on a multi-valued calc get.
  110. func (a *HistogramAggregation) OrderByAggregationAndMetric(aggName, metric string, asc bool) *HistogramAggregation {
  111. // {
  112. // "aggs" : {
  113. // "genders" : {
  114. // "terms" : {
  115. // "field" : "gender",
  116. // "order" : { "height_stats.avg" : "desc" }
  117. // },
  118. // "aggs" : {
  119. // "height_stats" : { "stats" : { "field" : "height" } }
  120. // }
  121. // }
  122. // }
  123. // }
  124. a.order = aggName + "." + metric
  125. a.orderAsc = asc
  126. return a
  127. }
  128. func (a *HistogramAggregation) MinDocCount(minDocCount int64) *HistogramAggregation {
  129. a.minDocCount = &minDocCount
  130. return a
  131. }
  132. func (a *HistogramAggregation) ExtendedBounds(min, max float64) *HistogramAggregation {
  133. a.minBounds = &min
  134. a.maxBounds = &max
  135. return a
  136. }
  137. func (a *HistogramAggregation) ExtendedBoundsMin(min float64) *HistogramAggregation {
  138. a.minBounds = &min
  139. return a
  140. }
  141. func (a *HistogramAggregation) MinBounds(min float64) *HistogramAggregation {
  142. a.minBounds = &min
  143. return a
  144. }
  145. func (a *HistogramAggregation) ExtendedBoundsMax(max float64) *HistogramAggregation {
  146. a.maxBounds = &max
  147. return a
  148. }
  149. func (a *HistogramAggregation) MaxBounds(max float64) *HistogramAggregation {
  150. a.maxBounds = &max
  151. return a
  152. }
  153. // Offset into the histogram
  154. func (a *HistogramAggregation) Offset(offset float64) *HistogramAggregation {
  155. a.offset = &offset
  156. return a
  157. }
  158. func (a *HistogramAggregation) Source() (interface{}, error) {
  159. // Example:
  160. // {
  161. // "aggs" : {
  162. // "prices" : {
  163. // "histogram" : {
  164. // "field" : "price",
  165. // "interval" : 50
  166. // }
  167. // }
  168. // }
  169. // }
  170. //
  171. // This method returns only the { "histogram" : { ... } } part.
  172. source := make(map[string]interface{})
  173. opts := make(map[string]interface{})
  174. source["histogram"] = opts
  175. // ValuesSourceAggregationBuilder
  176. if a.field != "" {
  177. opts["field"] = a.field
  178. }
  179. if a.script != nil {
  180. src, err := a.script.Source()
  181. if err != nil {
  182. return nil, err
  183. }
  184. opts["script"] = src
  185. }
  186. if a.missing != nil {
  187. opts["missing"] = a.missing
  188. }
  189. opts["interval"] = a.interval
  190. if a.order != "" {
  191. o := make(map[string]interface{})
  192. if a.orderAsc {
  193. o[a.order] = "asc"
  194. } else {
  195. o[a.order] = "desc"
  196. }
  197. opts["order"] = o
  198. }
  199. if a.offset != nil {
  200. opts["offset"] = *a.offset
  201. }
  202. if a.minDocCount != nil {
  203. opts["min_doc_count"] = *a.minDocCount
  204. }
  205. if a.minBounds != nil || a.maxBounds != nil {
  206. bounds := make(map[string]interface{})
  207. if a.minBounds != nil {
  208. bounds["min"] = a.minBounds
  209. }
  210. if a.maxBounds != nil {
  211. bounds["max"] = a.maxBounds
  212. }
  213. opts["extended_bounds"] = bounds
  214. }
  215. // AggregationBuilder (SubAggregations)
  216. if len(a.subAggregations) > 0 {
  217. aggsMap := make(map[string]interface{})
  218. source["aggregations"] = aggsMap
  219. for name, aggregate := range a.subAggregations {
  220. src, err := aggregate.Source()
  221. if err != nil {
  222. return nil, err
  223. }
  224. aggsMap[name] = src
  225. }
  226. }
  227. // Add Meta data if available
  228. if len(a.meta) > 0 {
  229. source["meta"] = a.meta
  230. }
  231. return source, nil
  232. }