Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'agg-top-metrics' of git://github.com/mbalabin/elastic i…
…nto mbalabin-agg-top-metrics
- Loading branch information
Showing
5 changed files
with
234 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package elastic | ||
|
||
import "errors" | ||
|
||
// TopMetricsAggregation selects metrics from the document with the largest or smallest "sort" value. | ||
// top_metrics is fairly similar to top_hits in spirit but because it is more limited it is able to do | ||
// its job using less memory and is often faster. | ||
// | ||
// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-top-metrics.html | ||
type TopMetricsAggregation struct { | ||
fields []string | ||
sorter Sorter | ||
size int | ||
} | ||
|
||
func NewTopMetricsAggregation() *TopMetricsAggregation { | ||
return &TopMetricsAggregation{} | ||
} | ||
|
||
// Field adds a field to run aggregation against. | ||
func (a *TopMetricsAggregation) Field(field string) *TopMetricsAggregation { | ||
a.fields = append(a.fields, field) | ||
return a | ||
} | ||
|
||
// Sort adds a sort order. | ||
func (a *TopMetricsAggregation) Sort(field string, ascending bool) *TopMetricsAggregation { | ||
a.sorter = SortInfo{Field: field, Ascending: ascending} | ||
return a | ||
} | ||
|
||
// SortWithInfo adds a sort order. | ||
func (a *TopMetricsAggregation) SortWithInfo(info SortInfo) *TopMetricsAggregation { | ||
a.sorter = info | ||
return a | ||
} | ||
|
||
// SortBy adds a sort order. | ||
func (a *TopMetricsAggregation) SortBy(sorter Sorter) *TopMetricsAggregation { | ||
a.sorter = sorter | ||
return a | ||
} | ||
|
||
// Size sets the number of top documents returned by the aggregation. The default size is 1. | ||
func (a *TopMetricsAggregation) Size(size int) *TopMetricsAggregation { | ||
a.size = size | ||
return a | ||
} | ||
|
||
func (a *TopMetricsAggregation) Source() (interface{}, error) { | ||
params := make(map[string]interface{}) | ||
|
||
if len(a.fields) == 0 { | ||
return nil, errors.New("field list is required for the top metrics aggregation") | ||
} | ||
metrics := make([]interface{}, len(a.fields)) | ||
for idx, field := range a.fields { | ||
metrics[idx] = map[string]string{"field": field} | ||
} | ||
params["metrics"] = metrics | ||
|
||
if a.sorter == nil { | ||
return nil, errors.New("sorter is required for the top metrics aggregation") | ||
} | ||
sortSource, err := a.sorter.Source() | ||
if err != nil { | ||
return nil, err | ||
} | ||
params["sort"] = sortSource | ||
|
||
if a.size > 1 { | ||
params["size"] = a.size | ||
} | ||
|
||
source := map[string]interface{}{ | ||
"top_metrics": params, | ||
} | ||
return source, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package elastic | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
) | ||
|
||
func TestTopMetricsAggregation(t *testing.T) { | ||
agg := NewTopMetricsAggregation(). | ||
Sort("f1", false). | ||
Field("a"). | ||
Field("b"). | ||
Size(3) | ||
src, err := agg.Source() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
data, err := json.Marshal(src) | ||
if err != nil { | ||
t.Fatalf("marshaling to JSON failed: %v", err) | ||
} | ||
got := string(data) | ||
expected := `{"top_metrics":{"metrics":[{"field":"a"},{"field":"b"}],"size":3,"sort":{"f1":{"order":"desc"}}}}` | ||
if got != expected { | ||
t.Errorf("expected\n%s\n,got:\n%s", expected, got) | ||
} | ||
} | ||
|
||
func TestTopMetricsAggregation_SortBy(t *testing.T) { | ||
agg := NewTopMetricsAggregation(). | ||
SortBy(SortByDoc{}). | ||
Field("a") | ||
src, err := agg.Source() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
data, err := json.Marshal(src) | ||
if err != nil { | ||
t.Fatalf("marshaling to JSON failed: %v", err) | ||
} | ||
got := string(data) | ||
expected := `{"top_metrics":{"metrics":[{"field":"a"}],"sort":"_doc"}}` | ||
if got != expected { | ||
t.Errorf("expected\n%s\n,got:\n%s", expected, got) | ||
} | ||
} | ||
|
||
func TestTopMetricsAggregation_SortWithInfo(t *testing.T) { | ||
agg := NewTopMetricsAggregation(). | ||
SortWithInfo(SortInfo{Field: "f2", Ascending: true, UnmappedType: "int"}). | ||
Field("b") | ||
src, err := agg.Source() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
data, err := json.Marshal(src) | ||
if err != nil { | ||
t.Fatalf("marshaling to JSON failed: %v", err) | ||
} | ||
got := string(data) | ||
expected := `{"top_metrics":{"metrics":[{"field":"b"}],"sort":{"f2":{"order":"asc","unmapped_type":"int"}}}}` | ||
if got != expected { | ||
t.Errorf("expected\n%s\n,got:\n%s", expected, got) | ||
} | ||
} | ||
|
||
func TestTopMetricsAggregation_FailNoSorter(t *testing.T) { | ||
agg := NewTopMetricsAggregation(). | ||
Field("a"). | ||
Field("b") | ||
_, err := agg.Source() | ||
if err == nil || err.Error() != "sorter is required for the top metrics aggregation" { | ||
t.Fatal(err) | ||
} | ||
} | ||
|
||
func TestTopMetricsAggregation_FailNoFields(t *testing.T) { | ||
agg := NewTopMetricsAggregation(). | ||
Sort("f1", false) | ||
_, err := agg.Source() | ||
if err == nil || err.Error() != "field list is required for the top metrics aggregation" { | ||
t.Fatal(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters