Handle elasticsearch "Filters" aggregation

  • What Grafana version are you using?

  • What datasource are you using?

  • What OS are you running grafana on?
    centos 7

  • What did you do?
    I am writting a panel plugin to support non-timeserise query like: terms,filters.
    I can receive data in callback: onDataReceived of my plugin with terms query,but get nothing with filters.So i debug the source of ElasticResponse and found that filters query returns an object as buckets instead of an array.
    ElasticResponse did not handle this situation.


  • What was the expected result?
    ElasticResponse can handle “keyed”(called by elasticsearch) buckets,So i can get Filters data in onDataReceived.

  • If related to metric query / data viz:

  • Include raw network request & response: get by opening Chrome Dev Tools (F12, Ctrl+Shift+I on windows, Cmd+Opt+I on Mac), go the network tab.

network request:


network response:

I write some code for reference only.

file:elastic_response.js line:213

      if (depth === maxDepth) {
        if (aggDef.type === 'date_histogram')  {
          this.processMetrics(esAgg, target, seriesList, props);
        } else if(aggDef.type === 'filters'){
          this.processAggregationKeyed(esAgg, target, docs, props);
        } else {
          this.processAggregationDocs(esAgg, aggDef, target, docs, props);
  ElasticResponse.prototype.processAggregationKeyed = function(esAgg, target, docs, props) {
    var metric, y, metricName, doc;
    _.forOwn(esAgg.buckets,function(bucket,key) {
      doc = _.defaults({}, props);
      doc['filterKey'] = key;
      for (y = 0; y < target.metrics.length; y++) {
        metric = target.metrics[y];

        switch(metric.type) {
          case "count": {
            metricName = this._getMetricName(metric.type);
            doc[metricName] = bucket.doc_count;
          case 'extended_stats': {
            for (var statName in metric.meta) {
              if (!metric.meta[statName]) {

              var stats = bucket[metric.id];
              // add stats that are in nested obj to top level obj
              stats.std_deviation_bounds_upper = stats.std_deviation_bounds.upper;
              stats.std_deviation_bounds_lower = stats.std_deviation_bounds.lower;

              metricName = this._getMetricName(statName);
              doc[metricName] = stats[statName];
          default:  {
            metricName = this._getMetricName(metric.type);
            var otherMetrics = _.filter(target.metrics, {type: metric.type});

            // if more of the same metric type include field field name in property
            if (otherMetrics.length > 1) {
              metricName += ' ' + metric.field;

            doc[metricName] = bucket[metric.id].value;

I created an issue#8834 (maybe not a proper way) for this post,but did not get satisfied answer.

@torkel said:

This works as expected, you will get processed response. Panel plugins do not get the raw ES response as panels should handle many types of datasources.
Please use community site, development category for plugin development questions

I agree with him.
But it is panel`s job to decide whether/how to handle processed response and for now Elasticsearch datasource did not process the raw ES response to processed response very well.

What does the datasource return for your query? (the processed result, what do you get in the panel)

I got nothing. dataList is an empty array.

What’s your point about this?@torkel
(The words fail to convey the meaning)

Point? Was just curious.

It should work similar to terms aggregation, so it’s strange that you get nothing back

terms aggregation returns array while filters returns object

Object? You said it returned nothing

I mean raw ES response returns object.
processed result is empty.

First of all, I do not have a group by time with query.