esquery/aggs_metric.go

466 lines
14 KiB
Go

package esquery
import "github.com/fatih/structs"
// BaseAgg contains several fields that are common for all aggregation types.
type BaseAgg struct {
name string
apiName string
*BaseAggParams `structs:",flatten"`
}
// BaseAggParams contains fields that are common to most metric-aggregation
// types.
type BaseAggParams struct {
// Field is the name of the field to aggregate on.
Field string `structs:"field"`
// Miss is a value to provide for documents that are missing a value for the
// field.
Miss interface{} `structs:"missing,omitempty"`
}
func newBaseAgg(apiName, name, field string) *BaseAgg {
return &BaseAgg{
name: name,
apiName: apiName,
BaseAggParams: &BaseAggParams{
Field: field,
},
}
}
// Name returns the name of the aggregation, allowing implementation of the
// Aggregation interface.
func (agg *BaseAgg) Name() string {
return agg.name
}
// Map returns a map representation of the aggregation, implementing the
// Mappable interface.
func (agg *BaseAgg) Map() map[string]interface{} {
return map[string]interface{}{
agg.apiName: structs.Map(agg.BaseAggParams),
}
}
// AvgAgg represents an aggregation of type "avg", as described in
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-avg-aggregation.html
type AvgAgg struct {
*BaseAgg `structs:",flatten"`
}
// Avg creates an aggregation of type "avg", with the provided name and on the
// provided field.
func Avg(name, field string) *AvgAgg {
return &AvgAgg{
BaseAgg: newBaseAgg("avg", name, field),
}
}
// Missing sets the value to provide for documents missing a value for the
// selected field.
func (agg *AvgAgg) Missing(val interface{}) *AvgAgg {
agg.Miss = val
return agg
}
//----------------------------------------------------------------------------//
// WeightedAvgAgg represents an aggregation of type "weighted_avg", as described
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-weight-avg-aggregation.html
type WeightedAvgAgg struct {
name string
apiName string
// Val is the value component of the aggregation
Val *BaseAggParams `structs:"value"`
// Weig is the weight component of the aggregation
Weig *BaseAggParams `structs:"weight"`
}
// WeightedAvg creates a new aggregation of type "weighted_agg" with the
// provided name.
func WeightedAvg(name string) *WeightedAvgAgg {
return &WeightedAvgAgg{
name: name,
apiName: "weighted_avg",
}
}
// Name returns the name of the aggregation.
func (agg *WeightedAvgAgg) Name() string {
return agg.name
}
// Value sets the value field and optionally a value to use when records are
// missing a value for the field.
func (agg *WeightedAvgAgg) Value(field string, missing ...interface{}) *WeightedAvgAgg {
agg.Val = new(BaseAggParams)
agg.Val.Field = field
if len(missing) > 0 {
agg.Val.Miss = missing[len(missing)-1]
}
return agg
}
// Weight sets the weight field and optionally a value to use when records are
// missing a value for the field.
func (agg *WeightedAvgAgg) Weight(field string, missing ...interface{}) *WeightedAvgAgg {
agg.Weig = new(BaseAggParams)
agg.Weig.Field = field
if len(missing) > 0 {
agg.Weig.Miss = missing[len(missing)-1]
}
return agg
}
// Map returns a map representation of the aggregation, thus implementing the
// Mappable interface.
func (agg *WeightedAvgAgg) Map() map[string]interface{} {
return map[string]interface{}{
agg.apiName: structs.Map(agg),
}
}
//----------------------------------------------------------------------------//
// CardinalityAgg represents an aggregation of type "cardinality", as described
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html
type CardinalityAgg struct {
*BaseAgg `structs:",flatten"`
// PrecisionThr is the precision threshold of the aggregation
PrecisionThr uint16 `structs:"precision_threshold,omitempty"`
}
// Cardinality creates a new aggregation of type "cardinality" with the provided
// name and on the provided field.
func Cardinality(name, field string) *CardinalityAgg {
return &CardinalityAgg{
BaseAgg: newBaseAgg("cardinality", name, field),
}
}
// Missing sets the value to provide for records that are missing a value for
// the field.
func (agg *CardinalityAgg) Missing(val interface{}) *CardinalityAgg {
agg.Miss = val
return agg
}
// PrecisionThreshold sets the precision threshold of the aggregation.
func (agg *CardinalityAgg) PrecisionThreshold(val uint16) *CardinalityAgg {
agg.PrecisionThr = val
return agg
}
// Map returns a map representation of the aggregation, thus implementing the
// Mappable interface
func (agg *CardinalityAgg) Map() map[string]interface{} {
return map[string]interface{}{
agg.apiName: structs.Map(agg),
}
}
//----------------------------------------------------------------------------//
// MaxAgg represents an aggregation of type "max", as described in:
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-max-aggregation.html
type MaxAgg struct {
*BaseAgg `structs:",flatten"`
}
// Max creates a new aggregation of type "max", with the provided name and on
// the provided field.
func Max(name, field string) *MaxAgg {
return &MaxAgg{
BaseAgg: newBaseAgg("max", name, field),
}
}
// Missing sets the value to provide for records that are missing a value for
// the field.
func (agg *MaxAgg) Missing(val interface{}) *MaxAgg {
agg.Miss = val
return agg
}
//----------------------------------------------------------------------------//
// MinAgg represents an aggregation of type "min", as described in:
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-min-aggregation.html
type MinAgg struct {
*BaseAgg `structs:",flatten"`
}
// Min creates a new aggregation of type "min", with the provided name and on
// the provided field.
func Min(name, field string) *MinAgg {
return &MinAgg{
BaseAgg: newBaseAgg("min", name, field),
}
}
// Missing sets the value to provide for records that are missing a value for
// the field.
func (agg *MinAgg) Missing(val interface{}) *MinAgg {
agg.Miss = val
return agg
}
//----------------------------------------------------------------------------//
// SumAgg represents an aggregation of type "sum", as described in:
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-sum-aggregation.html
type SumAgg struct {
*BaseAgg `structs:",flatten"`
}
// Sum creates a new aggregation of type "sum", with the provided name and on
// the provided field.
func Sum(name, field string) *SumAgg {
return &SumAgg{
BaseAgg: newBaseAgg("sum", name, field),
}
}
// Missing sets the value to provide for records that are missing a value for
// the field.
func (agg *SumAgg) Missing(val interface{}) *SumAgg {
agg.Miss = val
return agg
}
//----------------------------------------------------------------------------//
// ValueCountAgg represents an aggregation of type "value_count", as described
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-valuecount-aggregation.html
type ValueCountAgg struct {
*BaseAgg `structs:",flatten"`
}
// ValueCount creates a new aggregation of type "value_count", with the provided
// name and on the provided field
func ValueCount(name, field string) *ValueCountAgg {
return &ValueCountAgg{
BaseAgg: newBaseAgg("value_count", name, field),
}
}
//----------------------------------------------------------------------------//
// PercentilesAgg represents an aggregation of type "percentiles", as described
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-percentile-aggregation.html
type PercentilesAgg struct {
*BaseAgg `structs:",flatten"`
// Prcnts is the aggregation's percentages
Prcnts []float32 `structs:"percents,omitempty"`
// Key denotes whether the aggregation is keyed or not
Key *bool `structs:"keyed,omitempty"`
// TDigest includes options for the TDigest algorithm
TDigest struct {
// Compression is the compression level to use
Compression uint16 `structs:"compression,omitempty"`
} `structs:"tdigest,omitempty"`
// HDR includes options for the HDR implementation
HDR struct {
// NumHistogramDigits defines the resolution of values for the histogram
// in number of significant digits
NumHistogramDigits uint8 `structs:"number_of_significant_value_digits,omitempty"`
} `structs:"hdr,omitempty"`
}
// Percentiles creates a new aggregation of type "percentiles" with the provided
// name and on the provided field.
func Percentiles(name, field string) *PercentilesAgg {
return &PercentilesAgg{
BaseAgg: newBaseAgg("percentiles", name, field),
}
}
// Percents sets the aggregation's percentages
func (agg *PercentilesAgg) Percents(percents ...float32) *PercentilesAgg {
agg.Prcnts = percents
return agg
}
// Missing sets the value to provide for records that are missing a value for
// the field.
func (agg *PercentilesAgg) Missing(val interface{}) *PercentilesAgg {
agg.Miss = val
return agg
}
// Keyed sets whether the aggregate is keyed or not.
func (agg *PercentilesAgg) Keyed(b bool) *PercentilesAgg {
agg.Key = &b
return agg
}
// Compression sets the compression level for the aggregation.
func (agg *PercentilesAgg) Compression(val uint16) *PercentilesAgg {
agg.TDigest.Compression = val
return agg
}
// NumHistogramDigits specifies the resolution of values for the histogram in
// number of significant digits.
func (agg *PercentilesAgg) NumHistogramDigits(val uint8) *PercentilesAgg {
agg.HDR.NumHistogramDigits = val
return agg
}
// Map returns a map representation of the aggregation, thus implementing the
// Mappable interface.
func (agg *PercentilesAgg) Map() map[string]interface{} {
return map[string]interface{}{
agg.apiName: structs.Map(agg),
}
}
//----------------------------------------------------------------------------//
// StatsAgg represents an aggregation of type "stats", as described in:
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-stats-aggregation.html
type StatsAgg struct {
*BaseAgg `structs:",flatten"`
}
// Stats creates a new "stats" aggregation with the provided name and on the
// provided field.
func Stats(name, field string) *StatsAgg {
return &StatsAgg{
BaseAgg: newBaseAgg("stats", name, field),
}
}
// Missing sets the value to provide for records missing a value for the field.
func (agg *StatsAgg) Missing(val interface{}) *StatsAgg {
agg.Miss = val
return agg
}
// ---------------------------------------------------------------------------//
// StringStatsAgg represents an aggregation of type "string_stats", as described
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-string-stats-aggregation.html
type StringStatsAgg struct {
*BaseAgg `structs:",flatten"`
// ShowDist indicates whether to ask ElasticSearch to return a probability
// distribution for all characters
ShowDist *bool `structs:"show_distribution,omitempty"`
}
// StringStats creates a new "string_stats" aggregation with the provided name
// and on the provided field.
func StringStats(name, field string) *StringStatsAgg {
return &StringStatsAgg{
BaseAgg: newBaseAgg("string_stats", name, field),
}
}
// Missing sets the value to provide for records missing a value for the field.
func (agg *StringStatsAgg) Missing(val interface{}) *StringStatsAgg {
agg.Miss = val
return agg
}
// ShowDistribution sets whether to show the probability distribution for all
// characters
func (agg *StringStatsAgg) ShowDistribution(b bool) *StringStatsAgg {
agg.ShowDist = &b
return agg
}
// Map returns a map representation of the aggregation, thus implementing the
// Mappable interface.
func (agg *StringStatsAgg) Map() map[string]interface{} {
return map[string]interface{}{
agg.apiName: structs.Map(agg),
}
}
// ---------------------------------------------------------------------------//
// TopHitsAgg represents an aggregation of type "top_hits", as described
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-top-hits-aggregation.html
type TopHitsAgg struct {
name string
from uint64
size uint64
sort []map[string]interface{}
source Source
}
// TopHits creates an aggregation of type "top_hits".
func TopHits(name string) *TopHitsAgg {
return &TopHitsAgg{
name: name,
}
}
// Name returns the name of the aggregation.
func (agg *TopHitsAgg) Name() string {
return agg.name
}
// From sets an offset from the first result to return.
func (agg *TopHitsAgg) From(offset uint64) *TopHitsAgg {
agg.from = offset
return agg
}
// Size sets the maximum number of top matching hits to return per bucket (the
// default is 3).
func (agg *TopHitsAgg) Size(size uint64) *TopHitsAgg {
agg.size = size
return agg
}
// Sort sets how the top matching hits should be sorted. By default the hits are
// sorted by the score of the main query.
func (agg *TopHitsAgg) Sort(name string, order Order) *TopHitsAgg {
agg.sort = append(agg.sort, map[string]interface{}{
name: map[string]interface{}{
"order": order,
},
})
return agg
}
// SourceIncludes sets the keys to return from the top matching documents.
func (agg *TopHitsAgg) SourceIncludes(keys ...string) *TopHitsAgg {
agg.source.includes = keys
return agg
}
// Map returns a map representation of the aggregation, thus implementing the
// Mappable interface.
func (agg *TopHitsAgg) Map() map[string]interface{} {
innerMap := make(map[string]interface{})
if agg.from > 0 {
innerMap["from"] = agg.from
}
if agg.size > 0 {
innerMap["size"] = agg.size
}
if len(agg.sort) > 0 {
innerMap["sort"] = agg.sort
}
if len(agg.source.includes) > 0 {
innerMap["_source"] = agg.source.Map()
}
return map[string]interface{}{
"top_hits": innerMap,
}
}