Aggregations

The QueryBuilder class has an aggregations method which allows you to add aggregations to the query. This page explains how this method can be used.

The aggregations method returns an instance of the Aggregations class, therefore this class’s method can be chained after the aggregations call. Please check the examples provided below to get an idea of how this works.

terms

This is a bucket-type aggregation which can count the number of individual values in a field. Detailed information on how to use this type of aggregation can be found on Elasticsearch’s documentation on the Terms aggregation

Code example:

query_builder = JayAPI::Elasticsearch::QueryBuilder.new
query_builder.aggregations.terms('genres', field: 'genre')

This would produce the following query:

{
  "query": {
    "match_all": { }
  },
  "aggs": {
    "genres": {
      "terms": {
        "field": "genre"
      }
    }
  }
}

avg

This is a single-value aggregation that calculates the average value of a field among all the matched documents. Detailed information on how to use this type of aggregation can be found on Elasticsearch’s documentation on the Avg aggregation

Code example:

query_builder = JayAPI::Elasticsearch::QueryBuilder.new
query_builder.aggregations.avg('avg_grade', field: 'grade')

This would produce the following query:

{
  "query": {
    "match_all": {
    }
  },
  "aggs": {
    "avg_grade": {
      "avg": {
        "field": "grade"
      }
    }
  }
}

sum

This is a single-value aggregation that calculates the sum of the values in the specified field through all the matched documents. Detailed information on how to use this type of aggregation can be found on Elasticsearch’s documentation on the Sum aggregation

Code example:

query_builder = JayAPI::Elasticsearch::QueryBuilder.new
query_builder.query.term(field: 'type', value: 'hat')
query_builder.aggregations.sum('hat_prices', field: 'price')

This would produce the following query:

{
  "query": {
    "term": {
      "type": {
        "value": "hat"
      }
    }
  },
  "aggs": {
    "hat_prices": {
      "sum": {
        "field": "price"
      }
    }
  }
}

max

This is a single-value aggregation that calculates the maximum value in the specified field among all matched documents. Detailed information on how to use this type of aggregation can be found on Elasticsearch’s documentation on the Max aggregation

Code example:

query_builder = JayAPI::Elasticsearch::QueryBuilder.new
query_builder.aggregations.max('max_price', field: 'price')

This would produce the following query:

{
  "query": {
    "match_all": { }
  },
  "aggs": {
    "max_price": {
      "max": {
        "field": "price"
      }
    }
  }
}

value_count

This is a single-value aggregation that calculates the number of non-null values in the specified field through all the matched documents. Detailed information on how to use this type of aggregation can be found on Elasticsearch’s documentation on the Value Count aggregation

Code example:

query_builder = JayAPI::Elasticsearch::QueryBuilder.new
query_builder.aggregations.value_count('types_count', field: 'type')

This would produce the following query:

{
  "query": {
    "match_all": { }
  },
  "aggs": {
    "types_count": {
      "value_count": { "field": "type" }
    }
  }
}

filter

This is a single bucket aggregation that filters the set of documents using a query to narrow it down. It is normally used in conjunction with other aggregations to create break downs of the whole data set. Detailed information on how to use this type of aggregation can be found on Elasticsearch’s documentation on the Filter aggregation

Code example:

query_builder = JayAPI::Elasticsearch::QueryBuilder.new
query_builder.aggregations.avg('overall_avg_price', field: 'price')
query_builder.aggregations.filter('t_shirts') do |query|
  query.term(field: 'type', value: 't-shirt')
end.aggs do |aggs|
  aggs.avg('avg_price', field: 'price')
end

This would generate the following query:

{
  "query": { "match_all": {} },
  "aggs": {
    "overall_avg_price": { "avg": { "field": "price" } },
    "t_shirts": {
      "filter": { "term": { "type": { "value": "t-shirt" } } },
      "aggs": {
        "avg_price": { "avg": { "field": "price" } }
      }
    }
  }
}

scripted_metric

This is a special type of single-value aggregation which can be used to build custom aggregations that return a single value. This type of aggregation takes a set of Painless scripts and returns a single value which can be a single number an array or even a map.

Detailed information on how to use this type of aggregation can be found on Elasticsearch’s documentation on the Scripted Metric aggregation

query_builder = JayAPI::Elasticsearch::QueryBuilder.new
query_builder.aggregations.scripted_metric(
  'profit',
  init_script: 'state.transactions = []',
  map_script: "state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)",
  combine_script: 'double profit = 0; for (t in state.transactions) { profit += t } return profit',
  reduce_script: 'double profit = 0; for (a in states) { profit += a } return profit'
)

The init_script is optional, the rest of the scripts are required.

The code above would produce the following query:

{
  "query": {
    "match_all": {
    }
  },
  "aggs": {
    "profit": {
      "scripted_metric": {
        "init_script": "state.transactions = []",
        "map_script": "state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)",
        "combine_script": "double profit = 0; for (t in state.transactions) { profit += t } return profit",
        "reduce_script": "double profit = 0; for (a in states) { profit += a } return profit"
      }
    }
  }
}

Warning

These scripts must be simple strings, they do not follow the pattern of other scripted elements in Elasticsearch’s DSL. Do not use QueryBuilder::Script objects here. Their use will produce unintended results.