elasticsearch
Loading

Metric aggregation reduce context

Serverless Stack

Use a Painless script to reduce values to produce the result of a scripted metric aggregation. A reduce script is run once on the coordinating node following a combine script (or a map script if no combine script is specified) and is optional as part of a full metric aggregation.

Warning

scripted_metric is not available in Elastic Cloud Serverless.

params (Map, read-only)
User-defined parameters passed in as part of the query.
states (Map)
Map with values available from the prior combine script (or a map script if no combine script is specified).
List, Map, String, or primitive
A value used as the result.

The standard Painless API is available.

To run the example, first install the eCommerce sample data.

Tip

You are viewing Phase 4 of 4 in the scripted metric aggregation pipeline. This reduces script runs once on the coordinating node to produce the final result from all shard data. This is the same complete example shown across all metric aggregation contexts.

In the following example, we build a query that analyzes the data to calculate the total number of products sold across all orders, using the map-reduce pattern where each shard processes documents locally and results are combined into a final total.

Initialization phase (sets up data structures):
The first code snippet is part of the init_script that initializes an empty array to collect quantity values from each document. It runs once per shard.

state.quantities = []
		

Map phase (processes each document):
The code in the map_script section runs for each document. It extracts the total quantity of products in each order and adds it to the shard's collection array.

state.quantities.add(doc['total_quantity'].value)
		

Combine phase (returns shard results):
The combine_script processes all the quantities collected in this shard by iterating through the array and summing all values. This reduces the data sent to the reduce phase from an array of individual quantities to a single total per shard.

int shardTotal = 0;

for (qty in state.quantities) {
  shardTotal += qty;
}

return shardTotal;
		

>Reduce phase (this context - merges all shard results):
Finally, the reduce_script merges results from all shards by iterating through each shard's total, and adds the results together to get the grand total of products sold across the entire dataset.

int grandTotal = 0;

for (shardTotal in states) {
  grandTotal += shardTotal;
}

return grandTotal;
		

The complete request looks like this:

GET kibana_sample_data_ecommerce/_search
{
  "size": 0,
  "aggs": {
	"total_quantity_sold": {
  	"scripted_metric": {
    	"init_script": "state.quantities = []",
    	"map_script": "state.quantities.add(doc['total_quantity'].value)",
    	"combine_script": """
          int shardTotal = 0;

          for (qty in state.quantities) {
            shardTotal += qty;
          }

          return shardTotal;
        """,
    	"reduce_script": """
          int grandTotal = 0;

          for (shardTotal in states) {
            grandTotal += shardTotal;
          }

          return grandTotal;
        """
      }
    }
  }
}