# SEARCH.AGGREGATE

> Compute analytics over matching documents.

Use `SEARCH.AGGREGATE` to compute metrics and buckets over matching documents.

The command takes two JSON arguments. The first is a filter, in the same language as [`SEARCH.QUERY`](/redis/commands/search/search-query), which selects the documents to aggregate; pass `'{}'` to cover the whole index. The second describes the aggregations to compute, as named entries such as `{"avg_price": {"$avg": {"field": "price"}}}`.

Metric operators like `$avg`, `$sum`, `$min`, `$max`, `$stats`, and `$cardinality` reduce the selected documents to a single number, while bucket operators like `$terms`, `$range`, `$histogram`, and `$dateHistogram` group them and report a count per bucket. Bucket operators accept nested `$aggs`, so you can compute a metric inside each bucket, for example the average price per category, and several aggregations can be requested in one call since they all run over the same selected document set.

See [Aggregations](/redis/search/aggregations) for the full operator reference and examples.

## Syntax

```redis
SEARCH.AGGREGATE <name> '<json_filter>' '<json_aggregations>'
```

`<json_filter>` is an [Upstash JSON filter](/redis/search/querying). The command accepts an index name or alias. See [Aggregations](/redis/search/aggregations) for the aggregation object and supported operators.

## Response

In `redis-cli --json`, the response is an object keyed by aggregation alias:

```json
{
  "avg_price": { "value": 49.99 },
  "by_category": { "buckets": [{ "key": "electronics", "docCount": 42 }] }
}
```

Raw RESP output may be rendered differently by client or protocol settings, but each top-level alias maps to its aggregation result. Returns `null` if the index does not exist.

## Examples

<AccordionGroup>

<Accordion title="Redis CLI" icon="terminal">

```bash
SEARCH.AGGREGATE products '{}' '{"avg_price": {"$avg": {"field": "price"}}}'
```

</Accordion>

<Accordion title="@upstash/redis" icon="node-js" iconType="brands">

```ts
import { Redis } from "@upstash/redis";

const redis = Redis.fromEnv();
const products = redis.search.index({ name: "products" });

const result = await products.aggregate({
  aggregations: {
    avg_price: { $avg: { field: "price" } },
  },
});
```

</Accordion>

<Accordion title="upstash_redis" icon="python" iconType="brands">

```python
from upstash_redis import Redis

redis = Redis.from_env()
products = redis.search.index(name="products")

result = products.aggregate(
    aggregations={"avg_price": {"$avg": {"field": "price"}}},
)
```

</Accordion>

<Accordion title="ioredis" icon="node-js" iconType="brands">

```ts
import IORedis from "ioredis";
import { createSearch } from "@upstash/search-ioredis";

const redis = new IORedis(process.env.REDIS_URL!);
const search = createSearch(redis);
const products = search.index({ name: "products" });

const result = await products.aggregate({
  aggregations: {
    avg_price: { $avg: { field: "price" } },
  },
});
```

</Accordion>

<Accordion title="node-redis" icon="node-js" iconType="brands">

```ts
import { createClient } from "redis";
import { createSearch } from "@upstash/search-redis";

const client = await createClient({ url: process.env.REDIS_URL })
  .on("error", console.error)
  .connect();
const search = createSearch(client);
const products = search.index({ name: "products" });

const result = await products.aggregate({
  aggregations: {
    avg_price: { $avg: { field: "price" } },
  },
});
```

</Accordion>

<Accordion title="curl">

```bash
curl -X POST https://YOUR_ENDPOINT.upstash.io \
  -H "Authorization: Bearer $UPSTASH_REDIS_REST_TOKEN" \
  -d '["SEARCH.AGGREGATE", "products", "{}", "{\"avg_price\": {\"$avg\": {\"field\": \"price\"}}}"]'
```

</Accordion>

</AccordionGroup>
