func (history *ElasticHistory) GetDailyHistogram(from, to string) ([]byte, error) { dailyAggregation := elastic.NewDateHistogramAggregation(). Field("date"). Interval("day"). Format("dd.MM.YYYY") rangeQuery := elastic.NewRangeQuery("date").From(from).To(to) searchResult, err := history.client.Search(). Index(history.index). Type(TYPE). Query(rangeQuery). Size(0). Aggregation("histogram", dailyAggregation). Do() if err != nil { return nil, err } hist, _ := searchResult.Aggregations.Histogram("histogram") log.Printf("In total there are %d buckets", len(hist.Buckets)) aggRes := make([]histogramResult, 30, 30) tDate := time.Now() tY, tM, tD := tDate.Date() d := time.Date(tY, tM, tD, 0, 0, 0, 0, time.UTC) for i := 0; i < 30; i++ { //aggregation results are for last 30days and for frontend they are prefilled aggRes[30-i-1] = histogramResult{Key: d.Unix(), DocCount: 0, Date: d.Format("02.01.2006")} d = d.Add(-24 * time.Hour) } for _, agg := range hist.Buckets { for i := 0; i < 30; i++ { if aggRes[i].Date == *agg.KeyAsString { aggRes[i].DocCount = agg.DocCount break } } } return json.Marshal(aggRes) }
func ExampleAggregations() { // Get a client to the local Elasticsearch instance. client, err := elastic.NewClient() if err != nil { // Handle error panic(err) } // Create an aggregation for users and a sub-aggregation for a date histogram of tweets (per year). timeline := elastic.NewTermsAggregation().Field("user").Size(10).OrderByCountDesc() histogram := elastic.NewDateHistogramAggregation().Field("created").Interval("year") timeline = timeline.SubAggregation("history", histogram) // Search with a term query searchResult, err := client.Search(). Index("twitter"). // search in index "twitter" Query(elastic.NewMatchAllQuery()). // return all results, but ... SearchType("count"). // ... do not return hits, just the count Aggregation("timeline", timeline). // add our aggregation to the query Pretty(true). // pretty print request and response JSON Do() // execute if err != nil { // Handle error panic(err) } // Access "timeline" aggregate in search result. agg, found := searchResult.Aggregations.Terms("timeline") if !found { log.Fatalf("we sould have a terms aggregation called %q", "timeline") } for _, userBucket := range agg.Buckets { // Every bucket should have the user field as key. user := userBucket.Key // The sub-aggregation history should have the number of tweets per year. histogram, found := userBucket.DateHistogram("history") if found { for _, year := range histogram.Buckets { fmt.Printf("user %q has %d tweets in %q\n", user, year.DocCount, year.KeyAsString) } } } }
// LSDateHistorgram builds the aggregation query using subaggregations. The result is a grouped time series // that Bosun can understand func LSDateHistogram(e *State, T miniprofiler.Timer, index_root, keystring, filter, interval, sduration, eduration, stat_field, rstat string, size int) (r *Results, err error) { r = new(Results) req, err := LSBaseQuery(e.now, index_root, keystring, filter, sduration, eduration, size) if err != nil { return nil, err } // Extended bounds and min doc count are required to get values back when the bucket value is 0 ts := elastic.NewDateHistogramAggregation().Field("@timestamp").Interval(strings.Replace(interval, "M", "n", -1)).MinDocCount(0).ExtendedBoundsMin(req.Start).ExtendedBoundsMax(req.End) if stat_field != "" { ts = ts.SubAggregation("stats", elastic.NewExtendedStatsAggregation().Field(stat_field)) switch rstat { case "avg", "min", "max", "sum", "sum_of_squares", "variance", "std_deviation": default: return r, fmt.Errorf("stat function %v not a valid option", rstat) } } if keystring == "" { req.Source = req.Source.Aggregation("ts", ts) result, err := timeLSRequest(e, T, req) if err != nil { return nil, err } ts, found := result.Aggregations.DateHistogram("ts") if !found { return nil, fmt.Errorf("expected time series not found in elastic reply") } series := make(Series) for _, v := range ts.Buckets { val := processBucketItem(v, rstat) if val != nil { series[time.Unix(v.Key/1000, 0).UTC()] = *val } } if len(series) == 0 { return r, nil } r.Results = append(r.Results, &Result{ Value: series, Group: make(opentsdb.TagSet), }) return r, nil } keys := req.KeyMatches aggregation := elastic.NewTermsAggregation().Field(keys[len(keys)-1].Key).Size(0) aggregation = aggregation.SubAggregation("ts", ts) for i := len(keys) - 2; i > -1; i-- { aggregation = elastic.NewTermsAggregation().Field(keys[i].Key).Size(0).SubAggregation("g_"+keys[i+1].Key, aggregation) } req.Source = req.Source.Aggregation("g_"+keys[0].Key, aggregation) result, err := timeLSRequest(e, T, req) if err != nil { return nil, err } top, ok := result.Aggregations.Terms("g_" + keys[0].Key) if !ok { return nil, fmt.Errorf("top key g_%v not found in result", keys[0].Key) } var desc func(*elastic.AggregationBucketKeyItem, opentsdb.TagSet, []lsKeyMatch) error desc = func(b *elastic.AggregationBucketKeyItem, tags opentsdb.TagSet, keys []lsKeyMatch) error { if ts, found := b.DateHistogram("ts"); found { if e.Squelched(tags) { return nil } series := make(Series) for _, v := range ts.Buckets { val := processBucketItem(v, rstat) if val != nil { series[time.Unix(v.Key/1000, 0).UTC()] = *val } } if len(series) == 0 { return nil } r.Results = append(r.Results, &Result{ Value: series, Group: tags.Copy(), }) return nil } if len(keys) < 1 { return nil } n, _ := b.Aggregations.Terms("g_" + keys[0].Key) for _, item := range n.Buckets { key := fmt.Sprint(item.Key) if keys[0].Pattern != nil && !keys[0].Pattern.MatchString(key) { continue } tags[keys[0].Key] = key if err := desc(item, tags.Copy(), keys[1:]); err != nil { return err } } return nil } for _, b := range top.Buckets { tags := make(opentsdb.TagSet) key := fmt.Sprint(b.Key) if keys[0].Pattern != nil && !keys[0].Pattern.MatchString(key) { continue } tags[keys[0].Key] = key if err := desc(b, tags, keys[1:]); err != nil { return nil, err } } return r, nil }