Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions aggs_histogram.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package osquery

type HistogramAggregation struct {
name string
field string
interval float64
offset *float64
minDocCount *int
aggs []Aggregation
}

// HistogramAgg creates a new histogram aggregation.
func HistogramAgg(name string, field string, interval float64) *HistogramAggregation {
return &HistogramAggregation{
name: name,
field: field,
interval: interval,
}
}

// Name returns the name of the aggregation.
func (agg *HistogramAggregation) Name() string {
return agg.name
}

// Offset sets an optional offset value.
func (agg *HistogramAggregation) Offset(offset float64) *HistogramAggregation {
agg.offset = &offset
return agg
}

// MinDocCount sets the optional minimum document count for buckets.
func (agg *HistogramAggregation) MinDocCount(min int) *HistogramAggregation {
agg.minDocCount = &min
return agg
}

// Aggs sets sub-aggregations for the histogram buckets.
func (agg *HistogramAggregation) Aggs(aggs ...Aggregation) *HistogramAggregation {
agg.aggs = aggs
return agg
}

// Map builds the OpenSearch aggregation map.
func (agg *HistogramAggregation) Map() map[string]interface{} {
histogramMap := map[string]interface{}{
"field": agg.field,
"interval": agg.interval,
}

if agg.offset != nil {
histogramMap["offset"] = *agg.offset
}
if agg.minDocCount != nil {
histogramMap["min_doc_count"] = *agg.minDocCount
}

outerMap := map[string]interface{}{
"histogram": histogramMap,
}

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
}
50 changes: 50 additions & 0 deletions aggs_histogram_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package osquery

import "testing"

func TestHistogramAggs(t *testing.T) {
runMapTests(t, []mapTest{
{
"histogram agg: basic",
HistogramAgg("hist", "price", 10),
map[string]interface{}{
"histogram": map[string]interface{}{
"field": "price",
"interval": 10.0,
},
},
},
{
"histogram agg: with offset and min_doc_count",
HistogramAgg("hist", "price", 5).
Offset(2).
MinDocCount(1),
map[string]interface{}{
"histogram": map[string]interface{}{
"field": "price",
"interval": 5.0,
"offset": 2.0,
"min_doc_count": 1,
},
},
},
{
"histogram agg: with sub-aggs",
HistogramAgg("hist", "price", 20).
Aggs(Avg("avg_price", "price")),
map[string]interface{}{
"histogram": map[string]interface{}{
"field": "price",
"interval": 20.0,
},
"aggs": map[string]interface{}{
"avg_price": map[string]interface{}{
"avg": map[string]interface{}{
"field": "price",
},
},
},
},
},
})
}
53 changes: 53 additions & 0 deletions aggs_reverse_nested.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package osquery

type ReverseNestedAggregation struct {
name string
path *string // Optional
aggs []Aggregation // Optional sub-aggregations
}

// ReverseNestedAgg creates a new reverse_nested aggregation.
func ReverseNestedAgg(name string) *ReverseNestedAggregation {
return &ReverseNestedAggregation{
name: name,
}
}

// Name returns the name of the aggregation.
func (agg *ReverseNestedAggregation) Name() string {
return agg.name
}

// Path sets the optional reverse_nested path.
func (agg *ReverseNestedAggregation) Path(p string) *ReverseNestedAggregation {
agg.path = &p
return agg
}

// Aggs sets optional sub-aggregations.
func (agg *ReverseNestedAggregation) Aggs(aggs ...Aggregation) *ReverseNestedAggregation {
agg.aggs = aggs
return agg
}

// Map builds the OpenSearch aggregation map.
func (agg *ReverseNestedAggregation) Map() map[string]interface{} {
reverseNestedBody := make(map[string]interface{})
if agg.path != nil {
reverseNestedBody["path"] = *agg.path
}

outerMap := map[string]interface{}{
"reverse_nested": reverseNestedBody,
}

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
}
39 changes: 39 additions & 0 deletions aggs_reverse_nested_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package osquery

import "testing"

func TestReverseNestedAggs(t *testing.T) {
runMapTests(t, []mapTest{
{
"reverse_nested agg: basic",
ReverseNestedAgg("to_parent"),
map[string]interface{}{
"reverse_nested": map[string]interface{}{},
},
},
{
"reverse_nested agg: with path",
ReverseNestedAgg("to_root").Path("some.nested.path"),
map[string]interface{}{
"reverse_nested": map[string]interface{}{
"path": "some.nested.path",
},
},
},
{
"reverse_nested agg: with sub-aggregations",
ReverseNestedAgg("to_parent").
Aggs(Cardinality("product_count", "group_id")),
map[string]interface{}{
"reverse_nested": map[string]interface{}{},
"aggs": map[string]interface{}{
"product_count": map[string]interface{}{
"cardinality": map[string]interface{}{
"field": "group_id",
},
},
},
},
},
})
}
22 changes: 22 additions & 0 deletions collapse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package osquery

type Collapse struct {
field string
Mappable
}

func CollapseField(field string) Collapse {
return Collapse{
field: field,
}
}

func (c Collapse) Map() map[string]interface{} {
outerMap := make(map[string]interface{})
if c.field != "" {
outerMap = map[string]interface{}{
"field": c.field,
}
}
return outerMap
}
15 changes: 15 additions & 0 deletions collapse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package osquery

import "testing"

func TestCollapse(t *testing.T) {
runMapTests(t, []mapTest{
{
"Basic collapse testing",
CollapseField("variant_group.group_id"),
map[string]interface{}{
"field": "variant_group.group_id",
},
},
})
}
18 changes: 2 additions & 16 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ type Source struct {
}

// Map returns a map representation of the Source object.
func (source Source) Map() map[string]interface{} {
m := make(map[string]interface{})
func (source Source) Map() map[string]any {
m := make(map[string]any)
if len(source.includes) > 0 {
m["includes"] = source.includes
}
Expand All @@ -22,17 +22,3 @@ func (source Source) Map() map[string]interface{} {
}
return m
}

// Sort represents a list of keys to sort by.
type Sort []map[string]interface{}

// Order is the ordering for a sort key (ascending, descending).
type Order string

const (
// OrderAsc represents sorting in ascending order.
OrderAsc Order = "asc"

// OrderDesc represents sorting in descending order.
OrderDesc Order = "desc"
)
Loading