Add support for nested aggregations and filtered aggregations
This commit is contained in:
parent
f7d496389e
commit
39f0dd59c1
|
@ -58,5 +58,39 @@ func TestAggregations(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"a complex, multi-aggregation, nested",
|
||||
Aggregate(
|
||||
NestedAgg("categories","categories").
|
||||
Aggs(TermsAgg("type","outdoors")),
|
||||
FilterAgg("filtered",
|
||||
Term("type", "t-shirt")),
|
||||
),
|
||||
map[string]interface{}{
|
||||
"aggs": map[string]interface{}{
|
||||
"categories": map[string]interface{}{
|
||||
"nested": map[string]interface{}{
|
||||
"path": "categories",
|
||||
},
|
||||
"aggs": map[string]interface{} {
|
||||
"type": map[string]interface{} {
|
||||
"terms": map[string]interface{} {
|
||||
"field": "outdoors",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"filtered": map[string]interface{}{
|
||||
"filter": map[string]interface{}{
|
||||
"term": map[string]interface{}{
|
||||
"type": map[string]interface{} {
|
||||
"value": "t-shirt",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package esquery
|
||||
|
||||
type FilterAggregation struct {
|
||||
name string
|
||||
filter Mappable
|
||||
aggs []Aggregation
|
||||
}
|
||||
|
||||
// Filter creates a new aggregation of type "filter". The method name includes
|
||||
// the "Agg" suffix to prevent conflict with the "filter" query.
|
||||
func FilterAgg(name string, filter Mappable) *FilterAggregation {
|
||||
return &FilterAggregation{
|
||||
name: name,
|
||||
filter: filter,
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the name of the aggregation.
|
||||
func (agg *FilterAggregation) Name() string {
|
||||
return agg.name
|
||||
}
|
||||
|
||||
// Filter sets the filter items
|
||||
func (agg *FilterAggregation) Filter(filter Mappable) *FilterAggregation {
|
||||
agg.filter = filter
|
||||
return agg
|
||||
}
|
||||
|
||||
// Aggs sets sub-aggregations for the aggregation.
|
||||
func (agg *FilterAggregation) Aggs(aggs ...Aggregation) *FilterAggregation {
|
||||
agg.aggs = aggs
|
||||
return agg
|
||||
}
|
||||
|
||||
func (agg *FilterAggregation) Map() map[string]interface{} {
|
||||
outerMap := map[string]interface{}{
|
||||
"filter": agg.filter.Map(),
|
||||
}
|
||||
|
||||
if len(agg.aggs) > 0 {
|
||||
subAggs := make(map[string]map[string]interface{})
|
||||
for _, sub := range agg.aggs {
|
||||
subAggs[sub.Name()] = sub.Map()
|
||||
}
|
||||
outerMap["aggs"] = subAggs
|
||||
}
|
||||
|
||||
return outerMap
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package esquery
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFilterAggs(t *testing.T) {
|
||||
runMapTests(t, []mapTest{
|
||||
{
|
||||
"filter agg: simple",
|
||||
FilterAgg("filtered", Term("type","t-shirt")),
|
||||
map[string]interface{}{
|
||||
"filter": map[string]interface{}{
|
||||
"term": map[string]interface{} {
|
||||
"type": map[string]interface{} {
|
||||
"value": "t-shirt",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"filter agg: with aggs",
|
||||
FilterAgg("filtered", Term("type","t-shirt")).
|
||||
Aggs(Avg("avg_price","price")),
|
||||
map[string]interface{}{
|
||||
"filter": map[string]interface{}{
|
||||
"term": map[string]interface{} {
|
||||
"type": map[string]interface{} {
|
||||
"value": "t-shirt",
|
||||
},
|
||||
},
|
||||
},
|
||||
"aggs": map[string]interface{} {
|
||||
"avg_price": map[string]interface{} {
|
||||
"avg": map[string]interface{}{
|
||||
"field": "price",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package esquery
|
||||
|
||||
type NestedAggregation struct {
|
||||
name string
|
||||
path string
|
||||
aggs []Aggregation
|
||||
}
|
||||
|
||||
// NestedAgg creates a new aggregation of type "nested". The method name includes
|
||||
// the "Agg" suffix to prevent conflict with the "nested" query.
|
||||
func NestedAgg(name string, path string) *NestedAggregation {
|
||||
return &NestedAggregation{
|
||||
name: name,
|
||||
path: path,
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the name of the aggregation.
|
||||
func (agg *NestedAggregation) Name() string {
|
||||
return agg.name
|
||||
}
|
||||
|
||||
// NumberOfFragments sets the aggregations path
|
||||
func (agg *NestedAggregation) Path(p string) *NestedAggregation {
|
||||
agg.path = p
|
||||
return agg
|
||||
}
|
||||
|
||||
// Aggs sets sub-aggregations for the aggregation.
|
||||
func (agg *NestedAggregation) Aggs(aggs ...Aggregation) *NestedAggregation {
|
||||
agg.aggs = aggs
|
||||
return agg
|
||||
}
|
||||
|
||||
func (agg *NestedAggregation) Map() map[string]interface{} {
|
||||
innerMap := map[string]interface{}{
|
||||
"path": agg.path,
|
||||
}
|
||||
|
||||
outerMap := map[string]interface{}{
|
||||
"nested": innerMap,
|
||||
}
|
||||
|
||||
if len(agg.aggs) > 0 {
|
||||
subAggs := make(map[string]map[string]interface{})
|
||||
for _, sub := range agg.aggs {
|
||||
subAggs[sub.Name()] = sub.Map()
|
||||
}
|
||||
outerMap["aggs"] = subAggs
|
||||
}
|
||||
|
||||
return outerMap
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package esquery
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNestedAggs(t *testing.T) {
|
||||
runMapTests(t, []mapTest{
|
||||
{
|
||||
"nested agg: simple",
|
||||
NestedAgg("simple", "categories"),
|
||||
map[string]interface{}{
|
||||
"nested": map[string]interface{}{
|
||||
"path": "categories",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"nested agg: with aggs",
|
||||
NestedAgg("more_nested", "authors").
|
||||
Aggs(TermsAgg("authors","name")),
|
||||
map[string]interface{}{
|
||||
"nested": map[string]interface{}{
|
||||
"path": "authors",
|
||||
},
|
||||
"aggs": map[string]interface{} {
|
||||
"authors": map[string]interface{} {
|
||||
"terms": map[string]interface{} {
|
||||
"field": "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue