search_aggs_bucket_date_range.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. import (
  6. "time"
  7. )
  8. // DateRangeAggregation is a range aggregation that is dedicated for
  9. // date values. The main difference between this aggregation and the
  10. // normal range aggregation is that the from and to values can be expressed
  11. // in Date Math expressions, and it is also possible to specify a
  12. // date format by which the from and to response fields will be returned.
  13. // Note that this aggregration includes the from value and excludes the to
  14. // value for each range.
  15. // See: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-aggregations-bucket-daterange-aggregation.html
  16. type DateRangeAggregation struct {
  17. field string
  18. script *Script
  19. subAggregations map[string]Aggregation
  20. meta map[string]interface{}
  21. keyed *bool
  22. unmapped *bool
  23. format string
  24. entries []DateRangeAggregationEntry
  25. }
  26. type DateRangeAggregationEntry struct {
  27. Key string
  28. From interface{}
  29. To interface{}
  30. }
  31. func NewDateRangeAggregation() *DateRangeAggregation {
  32. return &DateRangeAggregation{
  33. subAggregations: make(map[string]Aggregation),
  34. entries: make([]DateRangeAggregationEntry, 0),
  35. }
  36. }
  37. func (a *DateRangeAggregation) Field(field string) *DateRangeAggregation {
  38. a.field = field
  39. return a
  40. }
  41. func (a *DateRangeAggregation) Script(script *Script) *DateRangeAggregation {
  42. a.script = script
  43. return a
  44. }
  45. func (a *DateRangeAggregation) SubAggregation(name string, subAggregation Aggregation) *DateRangeAggregation {
  46. a.subAggregations[name] = subAggregation
  47. return a
  48. }
  49. // Meta sets the meta data to be included in the aggregation response.
  50. func (a *DateRangeAggregation) Meta(metaData map[string]interface{}) *DateRangeAggregation {
  51. a.meta = metaData
  52. return a
  53. }
  54. func (a *DateRangeAggregation) Keyed(keyed bool) *DateRangeAggregation {
  55. a.keyed = &keyed
  56. return a
  57. }
  58. func (a *DateRangeAggregation) Unmapped(unmapped bool) *DateRangeAggregation {
  59. a.unmapped = &unmapped
  60. return a
  61. }
  62. func (a *DateRangeAggregation) Format(format string) *DateRangeAggregation {
  63. a.format = format
  64. return a
  65. }
  66. func (a *DateRangeAggregation) AddRange(from, to interface{}) *DateRangeAggregation {
  67. a.entries = append(a.entries, DateRangeAggregationEntry{From: from, To: to})
  68. return a
  69. }
  70. func (a *DateRangeAggregation) AddRangeWithKey(key string, from, to interface{}) *DateRangeAggregation {
  71. a.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: from, To: to})
  72. return a
  73. }
  74. func (a *DateRangeAggregation) AddUnboundedTo(from interface{}) *DateRangeAggregation {
  75. a.entries = append(a.entries, DateRangeAggregationEntry{From: from, To: nil})
  76. return a
  77. }
  78. func (a *DateRangeAggregation) AddUnboundedToWithKey(key string, from interface{}) *DateRangeAggregation {
  79. a.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: from, To: nil})
  80. return a
  81. }
  82. func (a *DateRangeAggregation) AddUnboundedFrom(to interface{}) *DateRangeAggregation {
  83. a.entries = append(a.entries, DateRangeAggregationEntry{From: nil, To: to})
  84. return a
  85. }
  86. func (a *DateRangeAggregation) AddUnboundedFromWithKey(key string, to interface{}) *DateRangeAggregation {
  87. a.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: nil, To: to})
  88. return a
  89. }
  90. func (a *DateRangeAggregation) Lt(to interface{}) *DateRangeAggregation {
  91. a.entries = append(a.entries, DateRangeAggregationEntry{From: nil, To: to})
  92. return a
  93. }
  94. func (a *DateRangeAggregation) LtWithKey(key string, to interface{}) *DateRangeAggregation {
  95. a.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: nil, To: to})
  96. return a
  97. }
  98. func (a *DateRangeAggregation) Between(from, to interface{}) *DateRangeAggregation {
  99. a.entries = append(a.entries, DateRangeAggregationEntry{From: from, To: to})
  100. return a
  101. }
  102. func (a *DateRangeAggregation) BetweenWithKey(key string, from, to interface{}) *DateRangeAggregation {
  103. a.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: from, To: to})
  104. return a
  105. }
  106. func (a *DateRangeAggregation) Gt(from interface{}) *DateRangeAggregation {
  107. a.entries = append(a.entries, DateRangeAggregationEntry{From: from, To: nil})
  108. return a
  109. }
  110. func (a *DateRangeAggregation) GtWithKey(key string, from interface{}) *DateRangeAggregation {
  111. a.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: from, To: nil})
  112. return a
  113. }
  114. func (a *DateRangeAggregation) Source() (interface{}, error) {
  115. // Example:
  116. // {
  117. // "aggs" : {
  118. // "range" : {
  119. // "date_range": {
  120. // "field": "date",
  121. // "format": "MM-yyy",
  122. // "ranges": [
  123. // { "to": "now-10M/M" },
  124. // { "from": "now-10M/M" }
  125. // ]
  126. // }
  127. // }
  128. // }
  129. // }
  130. // }
  131. //
  132. // This method returns only the { "date_range" : { ... } } part.
  133. source := make(map[string]interface{})
  134. opts := make(map[string]interface{})
  135. source["date_range"] = opts
  136. // ValuesSourceAggregationBuilder
  137. if a.field != "" {
  138. opts["field"] = a.field
  139. }
  140. if a.script != nil {
  141. src, err := a.script.Source()
  142. if err != nil {
  143. return nil, err
  144. }
  145. opts["script"] = src
  146. }
  147. if a.keyed != nil {
  148. opts["keyed"] = *a.keyed
  149. }
  150. if a.unmapped != nil {
  151. opts["unmapped"] = *a.unmapped
  152. }
  153. if a.format != "" {
  154. opts["format"] = a.format
  155. }
  156. var ranges []interface{}
  157. for _, ent := range a.entries {
  158. r := make(map[string]interface{})
  159. if ent.Key != "" {
  160. r["key"] = ent.Key
  161. }
  162. if ent.From != nil {
  163. switch from := ent.From.(type) {
  164. case int, int16, int32, int64, float32, float64:
  165. r["from"] = from
  166. case *int, *int16, *int32, *int64, *float32, *float64:
  167. r["from"] = from
  168. case time.Time:
  169. r["from"] = from.Format(time.RFC3339)
  170. case *time.Time:
  171. r["from"] = from.Format(time.RFC3339)
  172. case string:
  173. r["from"] = from
  174. case *string:
  175. r["from"] = from
  176. }
  177. }
  178. if ent.To != nil {
  179. switch to := ent.To.(type) {
  180. case int, int16, int32, int64, float32, float64:
  181. r["to"] = to
  182. case *int, *int16, *int32, *int64, *float32, *float64:
  183. r["to"] = to
  184. case time.Time:
  185. r["to"] = to.Format(time.RFC3339)
  186. case *time.Time:
  187. r["to"] = to.Format(time.RFC3339)
  188. case string:
  189. r["to"] = to
  190. case *string:
  191. r["to"] = to
  192. }
  193. }
  194. ranges = append(ranges, r)
  195. }
  196. opts["ranges"] = ranges
  197. // AggregationBuilder (SubAggregations)
  198. if len(a.subAggregations) > 0 {
  199. aggsMap := make(map[string]interface{})
  200. source["aggregations"] = aggsMap
  201. for name, aggregate := range a.subAggregations {
  202. src, err := aggregate.Source()
  203. if err != nil {
  204. return nil, err
  205. }
  206. aggsMap[name] = src
  207. }
  208. }
  209. // Add Meta data if available
  210. if len(a.meta) > 0 {
  211. source["meta"] = a.meta
  212. }
  213. return source, nil
  214. }