You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

search_aggs_bucket_composite.go 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  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. // CompositeAggregation is a multi-bucket values source based aggregation
  6. // that can be used to calculate unique composite values from source documents.
  7. //
  8. // See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-composite-aggregation.html
  9. // for details.
  10. type CompositeAggregation struct {
  11. after map[string]interface{}
  12. size *int
  13. sources []CompositeAggregationValuesSource
  14. subAggregations map[string]Aggregation
  15. meta map[string]interface{}
  16. }
  17. // NewCompositeAggregation creates a new CompositeAggregation.
  18. func NewCompositeAggregation() *CompositeAggregation {
  19. return &CompositeAggregation{
  20. sources: make([]CompositeAggregationValuesSource, 0),
  21. subAggregations: make(map[string]Aggregation),
  22. }
  23. }
  24. // Size represents the number of composite buckets to return.
  25. // Defaults to 10 as of Elasticsearch 6.1.
  26. func (a *CompositeAggregation) Size(size int) *CompositeAggregation {
  27. a.size = &size
  28. return a
  29. }
  30. // AggregateAfter sets the values that indicate which composite bucket this
  31. // request should "aggregate after".
  32. func (a *CompositeAggregation) AggregateAfter(after map[string]interface{}) *CompositeAggregation {
  33. a.after = after
  34. return a
  35. }
  36. // Sources specifies the list of CompositeAggregationValuesSource instances to
  37. // use in the aggregation.
  38. func (a *CompositeAggregation) Sources(sources ...CompositeAggregationValuesSource) *CompositeAggregation {
  39. a.sources = append(a.sources, sources...)
  40. return a
  41. }
  42. // SubAggregations of this aggregation.
  43. func (a *CompositeAggregation) SubAggregation(name string, subAggregation Aggregation) *CompositeAggregation {
  44. a.subAggregations[name] = subAggregation
  45. return a
  46. }
  47. // Meta sets the meta data to be included in the aggregation response.
  48. func (a *CompositeAggregation) Meta(metaData map[string]interface{}) *CompositeAggregation {
  49. a.meta = metaData
  50. return a
  51. }
  52. // Source returns the serializable JSON for this aggregation.
  53. func (a *CompositeAggregation) Source() (interface{}, error) {
  54. // Example:
  55. // {
  56. // "aggs" : {
  57. // "my_composite_agg" : {
  58. // "composite" : {
  59. // "sources": [
  60. // {"my_term": { "terms": { "field": "product" }}},
  61. // {"my_histo": { "histogram": { "field": "price", "interval": 5 }}},
  62. // {"my_date": { "date_histogram": { "field": "timestamp", "interval": "1d" }}},
  63. // ],
  64. // "size" : 10,
  65. // "after" : ["a", 2, "c"]
  66. // }
  67. // }
  68. // }
  69. // }
  70. //
  71. // This method returns only the { "histogram" : { ... } } part.
  72. source := make(map[string]interface{})
  73. opts := make(map[string]interface{})
  74. source["composite"] = opts
  75. sources := make([]interface{}, len(a.sources))
  76. for i, s := range a.sources {
  77. src, err := s.Source()
  78. if err != nil {
  79. return nil, err
  80. }
  81. sources[i] = src
  82. }
  83. opts["sources"] = sources
  84. if a.size != nil {
  85. opts["size"] = *a.size
  86. }
  87. if a.after != nil {
  88. opts["after"] = a.after
  89. }
  90. // AggregationBuilder (SubAggregations)
  91. if len(a.subAggregations) > 0 {
  92. aggsMap := make(map[string]interface{})
  93. source["aggregations"] = aggsMap
  94. for name, aggregate := range a.subAggregations {
  95. src, err := aggregate.Source()
  96. if err != nil {
  97. return nil, err
  98. }
  99. aggsMap[name] = src
  100. }
  101. }
  102. // Add Meta data if available
  103. if len(a.meta) > 0 {
  104. source["meta"] = a.meta
  105. }
  106. return source, nil
  107. }
  108. // -- Generic interface for CompositeAggregationValues --
  109. // CompositeAggregationValuesSource specifies the interface that
  110. // all implementations for CompositeAggregation's Sources method
  111. // need to implement.
  112. //
  113. // The different implementations are described in
  114. // https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-composite-aggregation.html#_values_source_2.
  115. type CompositeAggregationValuesSource interface {
  116. Source() (interface{}, error)
  117. }
  118. // -- CompositeAggregationTermsValuesSource --
  119. // CompositeAggregationTermsValuesSource is a source for the CompositeAggregation that handles terms
  120. // it works very similar to a terms aggregation with slightly different syntax
  121. //
  122. // See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-composite-aggregation.html#_terms
  123. // for details.
  124. type CompositeAggregationTermsValuesSource struct {
  125. name string
  126. field string
  127. script *Script
  128. valueType string
  129. missing interface{}
  130. missingBucket *bool
  131. order string
  132. }
  133. // NewCompositeAggregationTermsValuesSource creates and initializes
  134. // a new CompositeAggregationTermsValuesSource.
  135. func NewCompositeAggregationTermsValuesSource(name string) *CompositeAggregationTermsValuesSource {
  136. return &CompositeAggregationTermsValuesSource{
  137. name: name,
  138. }
  139. }
  140. // Field to use for this source.
  141. func (a *CompositeAggregationTermsValuesSource) Field(field string) *CompositeAggregationTermsValuesSource {
  142. a.field = field
  143. return a
  144. }
  145. // Script to use for this source.
  146. func (a *CompositeAggregationTermsValuesSource) Script(script *Script) *CompositeAggregationTermsValuesSource {
  147. a.script = script
  148. return a
  149. }
  150. // ValueType specifies the type of values produced by this source,
  151. // e.g. "string" or "date".
  152. func (a *CompositeAggregationTermsValuesSource) ValueType(valueType string) *CompositeAggregationTermsValuesSource {
  153. a.valueType = valueType
  154. return a
  155. }
  156. // Order specifies the order in the values produced by this source.
  157. // It can be either "asc" or "desc".
  158. func (a *CompositeAggregationTermsValuesSource) Order(order string) *CompositeAggregationTermsValuesSource {
  159. a.order = order
  160. return a
  161. }
  162. // Asc ensures the order of the values produced is ascending.
  163. func (a *CompositeAggregationTermsValuesSource) Asc() *CompositeAggregationTermsValuesSource {
  164. a.order = "asc"
  165. return a
  166. }
  167. // Desc ensures the order of the values produced is descending.
  168. func (a *CompositeAggregationTermsValuesSource) Desc() *CompositeAggregationTermsValuesSource {
  169. a.order = "desc"
  170. return a
  171. }
  172. // Missing specifies the value to use when the source finds a missing
  173. // value in a document.
  174. //
  175. // Deprecated: Use MissingBucket instead.
  176. func (a *CompositeAggregationTermsValuesSource) Missing(missing interface{}) *CompositeAggregationTermsValuesSource {
  177. a.missing = missing
  178. return a
  179. }
  180. // MissingBucket, if true, will create an explicit null bucket which represents
  181. // documents with missing values.
  182. func (a *CompositeAggregationTermsValuesSource) MissingBucket(missingBucket bool) *CompositeAggregationTermsValuesSource {
  183. a.missingBucket = &missingBucket
  184. return a
  185. }
  186. // Source returns the serializable JSON for this values source.
  187. func (a *CompositeAggregationTermsValuesSource) Source() (interface{}, error) {
  188. source := make(map[string]interface{})
  189. name := make(map[string]interface{})
  190. source[a.name] = name
  191. values := make(map[string]interface{})
  192. name["terms"] = values
  193. // field
  194. if a.field != "" {
  195. values["field"] = a.field
  196. }
  197. // script
  198. if a.script != nil {
  199. src, err := a.script.Source()
  200. if err != nil {
  201. return nil, err
  202. }
  203. values["script"] = src
  204. }
  205. // missing
  206. if a.missing != nil {
  207. values["missing"] = a.missing
  208. }
  209. // missing_bucket
  210. if a.missingBucket != nil {
  211. values["missing_bucket"] = *a.missingBucket
  212. }
  213. // value_type
  214. if a.valueType != "" {
  215. values["value_type"] = a.valueType
  216. }
  217. // order
  218. if a.order != "" {
  219. values["order"] = a.order
  220. }
  221. return source, nil
  222. }
  223. // -- CompositeAggregationHistogramValuesSource --
  224. // CompositeAggregationHistogramValuesSource is a source for the CompositeAggregation that handles histograms
  225. // it works very similar to a terms histogram with slightly different syntax
  226. //
  227. // See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-composite-aggregation.html#_histogram
  228. // for details.
  229. type CompositeAggregationHistogramValuesSource struct {
  230. name string
  231. field string
  232. script *Script
  233. valueType string
  234. missing interface{}
  235. missingBucket *bool
  236. order string
  237. interval float64
  238. }
  239. // NewCompositeAggregationHistogramValuesSource creates and initializes
  240. // a new CompositeAggregationHistogramValuesSource.
  241. func NewCompositeAggregationHistogramValuesSource(name string, interval float64) *CompositeAggregationHistogramValuesSource {
  242. return &CompositeAggregationHistogramValuesSource{
  243. name: name,
  244. interval: interval,
  245. }
  246. }
  247. // Field to use for this source.
  248. func (a *CompositeAggregationHistogramValuesSource) Field(field string) *CompositeAggregationHistogramValuesSource {
  249. a.field = field
  250. return a
  251. }
  252. // Script to use for this source.
  253. func (a *CompositeAggregationHistogramValuesSource) Script(script *Script) *CompositeAggregationHistogramValuesSource {
  254. a.script = script
  255. return a
  256. }
  257. // ValueType specifies the type of values produced by this source,
  258. // e.g. "string" or "date".
  259. func (a *CompositeAggregationHistogramValuesSource) ValueType(valueType string) *CompositeAggregationHistogramValuesSource {
  260. a.valueType = valueType
  261. return a
  262. }
  263. // Missing specifies the value to use when the source finds a missing
  264. // value in a document.
  265. //
  266. // Deprecated: Use MissingBucket instead.
  267. func (a *CompositeAggregationHistogramValuesSource) Missing(missing interface{}) *CompositeAggregationHistogramValuesSource {
  268. a.missing = missing
  269. return a
  270. }
  271. // MissingBucket, if true, will create an explicit null bucket which represents
  272. // documents with missing values.
  273. func (a *CompositeAggregationHistogramValuesSource) MissingBucket(missingBucket bool) *CompositeAggregationHistogramValuesSource {
  274. a.missingBucket = &missingBucket
  275. return a
  276. }
  277. // Order specifies the order in the values produced by this source.
  278. // It can be either "asc" or "desc".
  279. func (a *CompositeAggregationHistogramValuesSource) Order(order string) *CompositeAggregationHistogramValuesSource {
  280. a.order = order
  281. return a
  282. }
  283. // Asc ensures the order of the values produced is ascending.
  284. func (a *CompositeAggregationHistogramValuesSource) Asc() *CompositeAggregationHistogramValuesSource {
  285. a.order = "asc"
  286. return a
  287. }
  288. // Desc ensures the order of the values produced is descending.
  289. func (a *CompositeAggregationHistogramValuesSource) Desc() *CompositeAggregationHistogramValuesSource {
  290. a.order = "desc"
  291. return a
  292. }
  293. // Interval specifies the interval to use.
  294. func (a *CompositeAggregationHistogramValuesSource) Interval(interval float64) *CompositeAggregationHistogramValuesSource {
  295. a.interval = interval
  296. return a
  297. }
  298. // Source returns the serializable JSON for this values source.
  299. func (a *CompositeAggregationHistogramValuesSource) Source() (interface{}, error) {
  300. source := make(map[string]interface{})
  301. name := make(map[string]interface{})
  302. source[a.name] = name
  303. values := make(map[string]interface{})
  304. name["histogram"] = values
  305. // field
  306. if a.field != "" {
  307. values["field"] = a.field
  308. }
  309. // script
  310. if a.script != nil {
  311. src, err := a.script.Source()
  312. if err != nil {
  313. return nil, err
  314. }
  315. values["script"] = src
  316. }
  317. // missing
  318. if a.missing != nil {
  319. values["missing"] = a.missing
  320. }
  321. // missing_bucket
  322. if a.missingBucket != nil {
  323. values["missing_bucket"] = *a.missingBucket
  324. }
  325. // value_type
  326. if a.valueType != "" {
  327. values["value_type"] = a.valueType
  328. }
  329. // order
  330. if a.order != "" {
  331. values["order"] = a.order
  332. }
  333. // Histogram-related properties
  334. values["interval"] = a.interval
  335. return source, nil
  336. }
  337. // -- CompositeAggregationDateHistogramValuesSource --
  338. // CompositeAggregationDateHistogramValuesSource is a source for the CompositeAggregation that handles date histograms
  339. // it works very similar to a date histogram aggregation with slightly different syntax
  340. //
  341. // See https://www.elastic.co/guide/en/elasticsearch/reference/7.4/search-aggregations-bucket-composite-aggregation.html#_date_histogram
  342. // for details.
  343. type CompositeAggregationDateHistogramValuesSource struct {
  344. name string
  345. field string
  346. script *Script
  347. valueType string
  348. missing interface{}
  349. missingBucket *bool
  350. order string
  351. interval interface{}
  352. fixedInterval interface{}
  353. calendarInterval interface{}
  354. format string
  355. timeZone string
  356. }
  357. // NewCompositeAggregationDateHistogramValuesSource creates and initializes
  358. // a new CompositeAggregationDateHistogramValuesSource.
  359. func NewCompositeAggregationDateHistogramValuesSource(name string) *CompositeAggregationDateHistogramValuesSource {
  360. return &CompositeAggregationDateHistogramValuesSource{
  361. name: name,
  362. }
  363. }
  364. // Field to use for this source.
  365. func (a *CompositeAggregationDateHistogramValuesSource) Field(field string) *CompositeAggregationDateHistogramValuesSource {
  366. a.field = field
  367. return a
  368. }
  369. // Script to use for this source.
  370. func (a *CompositeAggregationDateHistogramValuesSource) Script(script *Script) *CompositeAggregationDateHistogramValuesSource {
  371. a.script = script
  372. return a
  373. }
  374. // ValueType specifies the type of values produced by this source,
  375. // e.g. "string" or "date".
  376. func (a *CompositeAggregationDateHistogramValuesSource) ValueType(valueType string) *CompositeAggregationDateHistogramValuesSource {
  377. a.valueType = valueType
  378. return a
  379. }
  380. // Missing specifies the value to use when the source finds a missing
  381. // value in a document.
  382. //
  383. // Deprecated: Use MissingBucket instead.
  384. func (a *CompositeAggregationDateHistogramValuesSource) Missing(missing interface{}) *CompositeAggregationDateHistogramValuesSource {
  385. a.missing = missing
  386. return a
  387. }
  388. // MissingBucket, if true, will create an explicit null bucket which represents
  389. // documents with missing values.
  390. func (a *CompositeAggregationDateHistogramValuesSource) MissingBucket(missingBucket bool) *CompositeAggregationDateHistogramValuesSource {
  391. a.missingBucket = &missingBucket
  392. return a
  393. }
  394. // Order specifies the order in the values produced by this source.
  395. // It can be either "asc" or "desc".
  396. func (a *CompositeAggregationDateHistogramValuesSource) Order(order string) *CompositeAggregationDateHistogramValuesSource {
  397. a.order = order
  398. return a
  399. }
  400. // Asc ensures the order of the values produced is ascending.
  401. func (a *CompositeAggregationDateHistogramValuesSource) Asc() *CompositeAggregationDateHistogramValuesSource {
  402. a.order = "asc"
  403. return a
  404. }
  405. // Desc ensures the order of the values produced is descending.
  406. func (a *CompositeAggregationDateHistogramValuesSource) Desc() *CompositeAggregationDateHistogramValuesSource {
  407. a.order = "desc"
  408. return a
  409. }
  410. // Interval to use for the date histogram, e.g. "1d" or a numeric value like "60".
  411. //
  412. // Deprecated: Use FixedInterval or CalendarInterval instead.
  413. func (a *CompositeAggregationDateHistogramValuesSource) Interval(interval interface{}) *CompositeAggregationDateHistogramValuesSource {
  414. a.interval = interval
  415. return a
  416. }
  417. // FixedInterval to use for the date histogram, e.g. "1d" or a numeric value like "60".
  418. func (a *CompositeAggregationDateHistogramValuesSource) FixedInterval(fixedInterval interface{}) *CompositeAggregationDateHistogramValuesSource {
  419. a.fixedInterval = fixedInterval
  420. return a
  421. }
  422. // CalendarInterval to use for the date histogram, e.g. "1d" or a numeric value like "60".
  423. func (a *CompositeAggregationDateHistogramValuesSource) CalendarInterval(calendarInterval interface{}) *CompositeAggregationDateHistogramValuesSource {
  424. a.calendarInterval = calendarInterval
  425. return a
  426. }
  427. // Format to use for the date histogram, e.g. "strict_date_optional_time"
  428. func (a *CompositeAggregationDateHistogramValuesSource) Format(format string) *CompositeAggregationDateHistogramValuesSource {
  429. a.format = format
  430. return a
  431. }
  432. // TimeZone to use for the dates.
  433. func (a *CompositeAggregationDateHistogramValuesSource) TimeZone(timeZone string) *CompositeAggregationDateHistogramValuesSource {
  434. a.timeZone = timeZone
  435. return a
  436. }
  437. // Source returns the serializable JSON for this values source.
  438. func (a *CompositeAggregationDateHistogramValuesSource) Source() (interface{}, error) {
  439. source := make(map[string]interface{})
  440. name := make(map[string]interface{})
  441. source[a.name] = name
  442. values := make(map[string]interface{})
  443. name["date_histogram"] = values
  444. // field
  445. if a.field != "" {
  446. values["field"] = a.field
  447. }
  448. // script
  449. if a.script != nil {
  450. src, err := a.script.Source()
  451. if err != nil {
  452. return nil, err
  453. }
  454. values["script"] = src
  455. }
  456. // missing
  457. if a.missing != nil {
  458. values["missing"] = a.missing
  459. }
  460. // missing_bucket
  461. if a.missingBucket != nil {
  462. values["missing_bucket"] = *a.missingBucket
  463. }
  464. // value_type
  465. if a.valueType != "" {
  466. values["value_type"] = a.valueType
  467. }
  468. // order
  469. if a.order != "" {
  470. values["order"] = a.order
  471. }
  472. if a.format != "" {
  473. values["format"] = a.format
  474. }
  475. // DateHistogram-related properties
  476. if v := a.interval; v != nil {
  477. values["interval"] = v
  478. }
  479. if v := a.fixedInterval; v != nil {
  480. values["fixed_interval"] = v
  481. }
  482. if v := a.calendarInterval; v != nil {
  483. values["calendar_interval"] = v
  484. }
  485. // timeZone
  486. if a.timeZone != "" {
  487. values["time_zone"] = a.timeZone
  488. }
  489. return source, nil
  490. }