Skip to content

Commit 3227db6

Browse files
committed
1 parent 0f67219 commit 3227db6

6 files changed

+269
-7
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ Here are a few tips on how to get used to Elastic:
197197
- Bucket Aggregations
198198
- [x] Adjacency Matrix
199199
- [x] Children
200+
- [x] Auto-interval Date Histogram
200201
- [x] Date Histogram
201202
- [x] Date Range
202203
- [x] Diversified Sampler

ingest_get_pipeline_test.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ package elastic
66

77
import (
88
"context"
9-
"log"
10-
"os"
119
"testing"
1210
)
1311

@@ -48,7 +46,7 @@ func TestIngestGetPipelineURL(t *testing.T) {
4846
}
4947

5048
func TestIngestLifecycle(t *testing.T) {
51-
client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, "", 0)))
49+
client := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, "", 0)))
5250

5351
// With the new ES Docker images, XPack is already installed and returns a pipeline. So we cannot test for "no pipelines". Skipping for now.
5452
/*

search_aggs.go

+21-2
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,21 @@ func (a Aggregations) Histogram(name string) (*AggregationBucketHistogramItems,
473473
return nil, false
474474
}
475475

476+
// AutoDateHistogram returns auto date histogram aggregation results.
477+
// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-datehistogram-aggregation.html
478+
func (a Aggregations) AutoDateHistogram(name string) (*AggregationBucketHistogramItems, bool) {
479+
if raw, found := a[name]; found {
480+
agg := new(AggregationBucketHistogramItems)
481+
if raw == nil {
482+
return agg, true
483+
}
484+
if err := json.Unmarshal(raw, agg); err == nil {
485+
return agg, true
486+
}
487+
}
488+
return nil, false
489+
}
490+
476491
// DateHistogram returns date histogram aggregation results.
477492
// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-datehistogram-aggregation.html
478493
func (a Aggregations) DateHistogram(name string) (*AggregationBucketHistogramItems, bool) {
@@ -1391,8 +1406,9 @@ func (a *AggregationBucketAdjacencyMatrix) UnmarshalJSON(data []byte) error {
13911406
type AggregationBucketHistogramItems struct {
13921407
Aggregations
13931408

1394-
Buckets []*AggregationBucketHistogramItem //`json:"buckets"`
1395-
Meta map[string]interface{} // `json:"meta,omitempty"`
1409+
Buckets []*AggregationBucketHistogramItem //`json:"buckets"`
1410+
Interval interface{} // `json:"interval"` // can be numeric or a string
1411+
Meta map[string]interface{} // `json:"meta,omitempty"`
13961412
}
13971413

13981414
// UnmarshalJSON decodes JSON data and initializes an AggregationBucketHistogramItems structure.
@@ -1404,6 +1420,9 @@ func (a *AggregationBucketHistogramItems) UnmarshalJSON(data []byte) error {
14041420
if v, ok := aggs["buckets"]; ok && v != nil {
14051421
json.Unmarshal(v, &a.Buckets)
14061422
}
1423+
if v, ok := aggs["interval"]; ok && v != nil {
1424+
json.Unmarshal(v, &a.Interval)
1425+
}
14071426
if v, ok := aggs["meta"]; ok && v != nil {
14081427
json.Unmarshal(v, &a.Meta)
14091428
}
+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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+
5+
package elastic
6+
7+
// AutoDateHistogramAggregation is a multi-bucket aggregation similar to the
8+
// histogram except it can only be applied on date values, and the buckets num can bin pointed.
9+
// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.3/search-aggregations-bucket-autodatehistogram-aggregation.html
10+
type AutoDateHistogramAggregation struct {
11+
field string
12+
script *Script
13+
missing interface{}
14+
subAggregations map[string]Aggregation
15+
meta map[string]interface{}
16+
17+
buckets int
18+
minDocCount *int64
19+
timeZone string
20+
format string
21+
minimumInterval string
22+
}
23+
24+
// NewAutoDateHistogramAggregation creates a new AutoDateHistogramAggregation.
25+
func NewAutoDateHistogramAggregation() *AutoDateHistogramAggregation {
26+
return &AutoDateHistogramAggregation{
27+
subAggregations: make(map[string]Aggregation),
28+
}
29+
}
30+
31+
// Field on which the aggregation is processed.
32+
func (a *AutoDateHistogramAggregation) Field(field string) *AutoDateHistogramAggregation {
33+
a.field = field
34+
return a
35+
}
36+
37+
// Script on which th
38+
func (a *AutoDateHistogramAggregation) Script(script *Script) *AutoDateHistogramAggregation {
39+
a.script = script
40+
return a
41+
}
42+
43+
// Missing configures the value to use when documents miss a value.
44+
func (a *AutoDateHistogramAggregation) Missing(missing interface{}) *AutoDateHistogramAggregation {
45+
a.missing = missing
46+
return a
47+
}
48+
49+
// SubAggregation sub aggregation
50+
func (a *AutoDateHistogramAggregation) SubAggregation(name string, subAggregation Aggregation) *AutoDateHistogramAggregation {
51+
a.subAggregations[name] = subAggregation
52+
return a
53+
}
54+
55+
// Meta sets the meta data to be included in the aggregation response.
56+
func (a *AutoDateHistogramAggregation) Meta(metaData map[string]interface{}) *AutoDateHistogramAggregation {
57+
a.meta = metaData
58+
return a
59+
}
60+
61+
// Buckets buckets num by which the aggregation gets processed.
62+
func (a *AutoDateHistogramAggregation) Buckets(buckets int) *AutoDateHistogramAggregation {
63+
a.buckets = buckets
64+
return a
65+
}
66+
67+
// MinDocCount sets the minimum document count per bucket.
68+
// Buckets with less documents than this min value will not be returned.
69+
func (a *AutoDateHistogramAggregation) MinDocCount(minDocCount int64) *AutoDateHistogramAggregation {
70+
a.minDocCount = &minDocCount
71+
return a
72+
}
73+
74+
// TimeZone sets the timezone in which to translate dates before computing buckets.
75+
func (a *AutoDateHistogramAggregation) TimeZone(timeZone string) *AutoDateHistogramAggregation {
76+
a.timeZone = timeZone
77+
return a
78+
}
79+
80+
// Format sets the format to use for dates.
81+
func (a *AutoDateHistogramAggregation) Format(format string) *AutoDateHistogramAggregation {
82+
a.format = format
83+
return a
84+
}
85+
86+
// MinimumInterval accepted units for minimum_interval are: year/month/day/hour/minute/second
87+
func (a *AutoDateHistogramAggregation) MinimumInterval(interval string) *AutoDateHistogramAggregation {
88+
a.minimumInterval = interval
89+
return a
90+
}
91+
92+
// Source source for AutoDateHistogramAggregation
93+
func (a *AutoDateHistogramAggregation) Source() (interface{}, error) {
94+
// Example:
95+
// {
96+
// "aggs" : {
97+
// "articles_over_time" : {
98+
// "auto_date_histogram" : {
99+
// "field" : "date",
100+
// "buckets" : 10
101+
// }
102+
// }
103+
// }
104+
// }
105+
//
106+
// This method returns only the { "auto_date_histogram" : { ... } } part.
107+
108+
source := make(map[string]interface{})
109+
opts := make(map[string]interface{})
110+
source["auto_date_histogram"] = opts
111+
112+
// ValuesSourceAggregationBuilder
113+
if a.field != "" {
114+
opts["field"] = a.field
115+
}
116+
if a.script != nil {
117+
src, err := a.script.Source()
118+
if err != nil {
119+
return nil, err
120+
}
121+
opts["script"] = src
122+
}
123+
if a.missing != nil {
124+
opts["missing"] = a.missing
125+
}
126+
127+
if a.buckets > 0 {
128+
opts["buckets"] = a.buckets
129+
} else {
130+
opts["buckets"] = 10
131+
}
132+
133+
if a.minDocCount != nil {
134+
opts["min_doc_count"] = *a.minDocCount
135+
}
136+
if a.timeZone != "" {
137+
opts["time_zone"] = a.timeZone
138+
}
139+
if a.format != "" {
140+
opts["format"] = a.format
141+
}
142+
if a.minimumInterval != "" {
143+
opts["minimum_interval"] = a.minimumInterval
144+
}
145+
146+
// AggregationBuilder (SubAggregations)
147+
if len(a.subAggregations) > 0 {
148+
aggsMap := make(map[string]interface{})
149+
source["aggregations"] = aggsMap
150+
for name, aggregate := range a.subAggregations {
151+
src, err := aggregate.Source()
152+
if err != nil {
153+
return nil, err
154+
}
155+
aggsMap[name] = src
156+
}
157+
}
158+
159+
// Add Meta data if available
160+
if len(a.meta) > 0 {
161+
source["meta"] = a.meta
162+
}
163+
164+
return source, nil
165+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
5+
package elastic
6+
7+
import (
8+
"encoding/json"
9+
"testing"
10+
)
11+
12+
func TestAutoDateHistogramAggregation(t *testing.T) {
13+
agg := NewAutoDateHistogramAggregation().
14+
Field("date").
15+
Buckets(10)
16+
src, err := agg.Source()
17+
if err != nil {
18+
t.Fatal(err)
19+
}
20+
data, err := json.Marshal(src)
21+
if err != nil {
22+
t.Fatalf("marshaling to JSON failed: %v", err)
23+
}
24+
got := string(data)
25+
expected := `{"auto_date_histogram":{"buckets":10,"field":"date"}}`
26+
if got != expected {
27+
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
28+
}
29+
}
30+
31+
func TestAutoDateHistogramAggregationWithFormat(t *testing.T) {
32+
agg := NewAutoDateHistogramAggregation().Field("date").Format("yyyy-MM-dd").Buckets(5)
33+
src, err := agg.Source()
34+
if err != nil {
35+
t.Fatal(err)
36+
}
37+
data, err := json.Marshal(src)
38+
if err != nil {
39+
t.Fatalf("marshaling to JSON failed: %v", err)
40+
}
41+
got := string(data)
42+
expected := `{"auto_date_histogram":{"buckets":5,"field":"date","format":"yyyy-MM-dd"}}`
43+
if got != expected {
44+
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
45+
}
46+
}
47+
48+
func TestAutoDateHistogramAggregationWithMissing(t *testing.T) {
49+
agg := NewAutoDateHistogramAggregation().Field("date").Missing("1900")
50+
src, err := agg.Source()
51+
if err != nil {
52+
t.Fatal(err)
53+
}
54+
data, err := json.Marshal(src)
55+
if err != nil {
56+
t.Fatalf("marshaling to JSON failed: %v", err)
57+
}
58+
got := string(data)
59+
expected := `{"auto_date_histogram":{"field":"date","missing":"1900"}}`
60+
if got != expected {
61+
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
62+
}
63+
}

search_aggs_test.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ import (
1515

1616
// TestAggs is an integration test for most aggregation types.
1717
func TestAggs(t *testing.T) {
18-
//client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, "", log.LstdFlags)))
19-
client := setupTestClientAndCreateIndex(t)
18+
client := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, "", log.LstdFlags)))
2019

2120
tweet1 := tweet{
2221
User: "olivere",
@@ -102,6 +101,7 @@ func TestAggs(t *testing.T) {
102101
dateRangeAgg := NewDateRangeAggregation().Field("created").Lt("2012-01-01").Between("2012-01-01", "2013-01-01").Gt("2013-01-01")
103102
missingTagsAgg := NewMissingAggregation().Field("tags")
104103
retweetsHistoAgg := NewHistogramAggregation().Field("retweets").Interval(100)
104+
autoDateHistoAgg := NewAutoDateHistogramAggregation().Field("created").Buckets(2).Missing("1900-01-01").Format("yyyy-MM-dd")
105105
dateHistoAgg := NewDateHistogramAggregation().Field("created").Interval("year")
106106
dateHistoKeyedAgg := NewDateHistogramAggregation().Field("created").Interval("year").Keyed(true)
107107
retweetsFilterAgg := NewFilterAggregation().Filter(
@@ -139,6 +139,7 @@ func TestAggs(t *testing.T) {
139139
builder = builder.Aggregation("dateRange", dateRangeAgg)
140140
builder = builder.Aggregation("missingTags", missingTagsAgg)
141141
builder = builder.Aggregation("retweetsHisto", retweetsHistoAgg)
142+
builder = builder.Aggregation("autoDateHisto", autoDateHistoAgg)
142143
builder = builder.Aggregation("dateHisto", dateHistoAgg)
143144
builder = builder.Aggregation("dateHistoKeyed", dateHistoKeyedAgg)
144145
builder = builder.Aggregation("retweetsFilter", retweetsFilterAgg)
@@ -832,6 +833,21 @@ func TestAggs(t *testing.T) {
832833
t.Errorf("expected %v; got: %+v", 100.0, histoRes.Buckets[1].Key)
833834
}
834835

836+
// autoDateHisto
837+
autoDateHistoRes, found := agg.DateHistogram("autoDateHisto")
838+
if !found {
839+
t.Errorf("expected %v; got: %v", true, found)
840+
}
841+
if autoDateHistoRes == nil {
842+
t.Fatal("expected != nil; got: nil")
843+
}
844+
if len(autoDateHistoRes.Buckets) != 2 {
845+
t.Fatalf("expected %d; got: %d", 2, len(autoDateHistoRes.Buckets))
846+
}
847+
if autoDateHistoRes.Interval == nil {
848+
t.Fatalf("expected an interval; got: %v", autoDateHistoRes.Interval)
849+
}
850+
835851
// dateHisto
836852
dateHistoRes, found := agg.DateHistogram("dateHisto")
837853
if !found {

0 commit comments

Comments
 (0)