# Bucket Aggregates

Buckets Aggregates scan over a result set to group and count results which meet specific conditions. Result buckets and counts are then returned with the query response. For example "buckets": "high:price >= 200,mid:price >=50 AND price < 200,low:price < 50" defines price conditions for high, mid and low price buckets to put aggregate counts into.

### Before you start:

With this example the following bucket-aggregate steps must be defined in the query pipeline.

```
- id: bucket-aggregate
  params:
    buckets:
      bind: priceRangeBuckets
    name:
      constant: priceRange
- id: bucket-aggregate
  params:
    fields:
      bind: shippingOptionsBuckets
    name:
      constant: shippingOptions          
```

### Scenario: Ecommerce Search

**Search query:** `"q":"t-shirt"`

The following bucket aggregates will be used in this example:

1. Bucket `priceRange` (assuming `price` is a Float field)
2. Bucket `shippingOptions` (assuming `shippingOptions` is a String field)

**Description:**

Everything is run using the global search query as the starting point, so in this example all counts include records which satisfy the global text query `t-shirts`. Note: the global text query can be empty, in which case all records are included.

To start we'll to construct a query to return a count of all the high, mid and low price options for the query `t-shirts`.

```
{
    "variables": {
        "q": "t-shirt",
        "priceRangeBuckets": "high:price >= 200,mid:price >=50 AND price < 200,low:price < 50"
    }
}
```

#### Example response

```
 "aggregates": {
        "PriceRange": {
            "buckets": {
                "buckets": {
                    "high": {
                        "name": "high",
                        "count": 5596
                    },
                    "low": {
                        "name": "low",
                        "count": 6233
                    },
                    "mid": {
                        "name": "mid",
                        "count": 9249
                    }
                }
            }
        }
 }
```

#### Adding a shipping options bucket aggregate

Now let's add the shipping bucket aggregate to the query to return a count of all the high, mid and low price options, and a count of the free shipping or fast despatch options for the query `t-shirts`.

```
{
    "variables": {
        "q": "t-shirt",
        "priceRangeBuckets": "high:price >= 200,mid:price >=50 AND price < 200,low:price < 50",
        "shippingOptionsBuckets": "freeshipping:shippingOptions ~ ['FreeShipping'],fastdispatch:shippingOptions ~ ['FastDispatch']"
    }
}
```

#### Example response

```
"aggregates": {
        "PriceRange": {
            "buckets": {
                "buckets": {
                    "high": {
                        "name": "high",
                        "count": 5596
                    },
                    "low": {
                        "name": "low",
                        "count": 6233
                    },
                    "mid": {
                        "name": "mid",
                        "count": 9249
                    }
                }
            }
        },
        "shippingOptions": {
            "buckets": {
                "buckets": {
                    "freeshipping": {
                        "name": "freeshipping",
                        "count": 19460
                    },
                    "fastdispatch": {
                        "name": "fastdispatch",
                        "count": 1000
                    }
                }
            }
        }
 }
```

## Bucket Aggregate Filters:

A bucket aggregate filter is a pair, consisting of an bucket aggregate and a filter. Bucket Aggregate filters change the result set to reflect the filters that are specified with them.

### Before you start:

With this example the following bucket-aggregate-filter steps must be defined in the query pipeline.

```
- id: bucket-aggregate-filter
  params:
    buckets:
      bind: priceRangeBucket
    filter:
      bind: priceRangeFilter
    name:
      constant: PriceRange
- id: bucket-aggregate-filter
  params:
    buckets:
      bind: shippingOptionsBucket
    filter:
      bind: shippingOptionsFilter
    name:
      constant: shippingOption
```

### Continuing our Ecommerce search scenario

#### Filtering by price

If a user selects the low price filter, to only show t-shirts under $50. We want the *result set* to include products with `q = "t-shirt" AND price < 50`.

We also want the response to show counts for:

* shipping options where: `q = "t-shirt" AND price < 50`
* price where: `q = "t-shirt"`

In the query below we've added the filter `"price < 50"` to priceRangeFilter

```
{
    "variables": {
        "q": "t-shirt",
        "priceRangeBuckets": "high:price >= 200,mid:price >=50 AND price < 200,low:price < 50",
        "priceRangeFilter": "price < 50",
        "shippingOptionsBuckets": "freeshipping:shippingOptions ~ ['FreeShipping'],fastdispatch:shippingOptions ~ ['FastDispatch']"
    }
}
```

#### Example response

```
"aggregate_filters": {
        "PriceRange": {
            "buckets": {
                "buckets": {
                    "high": {
                        "name": "high",
                        "count": 5596
                    },
                    "low": {
                        "name": "low",
                        "count": 6233
                    },
                    "mid": {
                        "name": "mid",
                        "count": 9249
                    }
                }
            }
        },
        "shippingOptions": {
            "buckets": {
                "buckets": {
                    "freeshipping": {
                        "name": "freeshipping",
                        "count": 8545
                    },
                    "fastdispatch": {
                        "name": "fastdispatch",
                        "count": 635
                    }
                }
            }
        }
    },
```

#### Filtering by shipping

If a user selects the low price filter and free shipping, to only show t-shirts under $50 with free shipping. We want the *result set* to include products with `q = "t-shirt" AND price < 50 AND shippingOptions ~ ['FreeShipping']`.

We also want the response to show counts for:

* shipping options where: `q = "t-shirt" AND price < 50`
* price where: `q = "t-shirt" AND shippingOptions ~ ['FreeShipping']`

In the query below we've added the filter `"shippingOptions ~ ['FreeShipping']"` to shippingOptionsFilter

```
{
    "variables": {
        "q": "t-shirt",
        "priceRangeBuckets": "high:price >= 200,mid:price >=50 AND price < 200,low:price < 50",
        "priceRangeFilter": "price < 50",
        "shippingOptionsBuckets": "freeshipping:shippingOptions ~ ['FreeShipping'],fastdispatch:shippingOptions ~ ['FastDispatch']",
        "shippingOptionsFilter": "shippingOptions ~ ['FreeShipping']"
    }
}
```

#### Example response

```
"aggregate_filters": {
        "PriceRange": {
            "buckets": {
                "buckets": {
                    "high": {
                        "name": "high",
                        "count": 5565
                    },
                    "low": {
                        "name": "low",
                        "count": 3456
                    },
                    "mid": {
                        "name": "mid",
                        "count": 5650
                    }
                }
            }
        },
        "shippingOptions": {
            "buckets": {
                "buckets": {
                    "freeshipping": {
                        "name": "freeshipping",
                        "count": 8545
                    },
                    "fastdispatch": {
                        "name": "fastdispatch",
                        "count": 635
                    }
                }
            }
        }
    },
```

## Other techniques:

There may be scenarios where you want a record to be counted by more than one bucket. For example a customer rating bucket aggregation where you want a rating of 3.1 to be counted by the over 1 rating, over 2 rating and over 3 rating buckets. The solution to this example is to reverse the order of the buckets as you define them like the example below

```
{
    "variables": {
        "q": "t-shirt",
        "customerRatingBucket": "5+:(rating=5),4+:(rating>=4),3+:(rating>=3),2+:(rating>=2),1+:(rating>=1)"
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.search.io/developer-documentation/guides/feature-implementation/bucket-aggregates.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
