@@ -17,25 +17,101 @@ weight: 2
1717
1818## Overview
1919
20- [ ` FT.AGGREGATE ` ] ({{< relref "/commands/ft.aggregate" >}}) is a powerful Redis Query Engine (RQE) command for performing advanced data aggregation, filtering, sorting, and transformations on indexed documents. This reference page provides a structured breakdown of syntax, ordering rules, and best practices.
20+ [ ` FT.AGGREGATE ` ] ({{< relref "/commands/ft.aggregate" >}}) is a powerful Redis Query Engine (RQE) command for performing advanced data aggregation, filtering, sorting, and transformations on indexed hash or JSON documents. This reference page provides a structured breakdown of syntax, ordering rules, and best practices.
2121
22- The [ main aggregations page] ({{< relref "/develop/interact/search-and-query/advanced-concepts/aggregations" >}}) has a simple diagram showing how ` FT.AGGREGATE ` pipelines are constructed, but it's a bit too simplistic. For example, it's possible to create more complex aggregation pipelines by applying multiple ` REDUCE ` functions under a single GROUPBY clause, or you can chain groupings and mix in additional mapping steps: ` GROUPBY ` ... ` REDUCE ` ... ` APPLY ` ... ` GROUPBY ` ... ` REDUCE ` .
22+ The [ main aggregations page] ({{< relref "/develop/interact/search-and-query/advanced-concepts/aggregations" >}}) has a simple diagram showing how ` FT.AGGREGATE ` pipelines are constructed, but it doesn't tell the whole story. For example, it's possible to create more complex aggregation pipelines by applying multiple ` REDUCE ` functions under a single ` GROUPBY ` clause, or you can chain groupings and mix in additional mapping steps:
23+
24+ ` GROUPBY ` ... ` REDUCE ` ... ` APPLY ` ... ` GROUPBY ` ... ` REDUCE `
25+
26+ {{< note >}}
27+ The examples on this page are based on a hypothetical "products" data set, which you can [ download here] ( ./data/products.txt ) .
28+ {{< /note >}}
2329
2430## Syntax and expression ordering
2531
2632The ` FT.AGGREGATE ` command processes multiple expressions in a pipeline. Below is the recommended order:
2733
34+ 1 . ` index ` – the name of your index, which must be the first argument.
35+ 1 . ` query ` – your query, which must be the second argument.
28361 . ` FILTER ` – filters raw documents before transformations or aggregation.
29371 . ` LOAD ` – loads additional document attributes.
30381 . ` APPLY ` – applies transformations on fields.
31391 . ` GROUPBY ` – groups results by specific fields.
32401 . ` REDUCE ` – performs aggregations. For example, ` SUM ` , ` COUNT ` , and ` AVG ` .
33411 . ` SORTBY ` – orders the results based on specified fields.
34421 . ` LIMIT ` – restricts the number of results returned.
43+ 1 . ` DIALECT 2 ` - provides for more comprehensive syntax, for example using parameters in ` FILTER ` expressions.
44+
45+ Other keywords will be discussed toward the end of this page.
46+
47+ ## When to use ` @ `
3548
36- ## Using GROUPBY with multiple REDUCE
49+ Fields must be preceded by ` @ ` in the following circumstances:
50+
51+ - When referencing fields loaded from documents. In the following example, ` price ` is a document field and must be prefixed wit ` @ ` .
52+
53+ ``` sh
54+ FT.AGGREGATE products " *"
55+ LOAD 1 @price
56+ APPLY " @price * 1.1" AS adjusted_price
57+ SORTBY 2 @adjusted_price DESC
58+ LIMIT 0 10
59+ ```
60+
61+ - When referencing fields inside a ` FILTER ` clause that were loaded from documents.
62+
63+ ``` sh
64+ FT.AGGREGATE products " *"
65+ LOAD 1 @rating
66+ FILTER " @rating >= 4.5"
67+ LIMIT 0 10
68+ ```
69+
70+ - When referencing fields inside ` GROUPBY ` or ` REDUCE ` clauses.
71+
72+ ``` sh
73+ FT.AGGREGATE products " *"
74+ GROUPBY 1 @category
75+ REDUCE SUM 1 @price AS total_price
76+ LIMIT 0 10
77+ ```
78+
79+ - When referencing fields created by ` REDUCE ` in an ` APPLY ` or ` FILTER ` clauses.
80+
81+ ``` sh
82+ FT.AGGREGATE products " *"
83+ GROUPBY 1 @category
84+ REDUCE SUM 1 @price AS total_price
85+ APPLY " @total_price * 1.2" AS boosted_price
86+ FILTER " @total_price > 1000"
87+ LIMIT 0 10
88+ ```
89+
90+ - When referencing fields created by ` APPLY ` in another ` APPLY ` or ` FILTER ` clause.
91+
92+ ``` sh
93+ FT.AGGREGATE products " *"
94+ LOAD 2 @price @discount
95+ APPLY " @price - @discount" AS net_price
96+ APPLY " @net_price * 1.1" AS marked_up
97+ FILTER " @net_price > 200"
98+ LIMIT 0 10
99+ ```
100+
101+ - When referencing fields created by ` APPLY ` in a ` SORTBY ` clause.
102+
103+ ``` sh
104+ FT.AGGREGATE products " *"
105+ LOAD 2 @price @discount
106+ APPLY " @price - @discount" AS net_price
107+ SORTBY 2 @net_price DESC
108+ LIMIT 0 10
109+ ```
110+
111+ ## GROUPBY with multiple REDUCE operations
37112
38113` GROUPBY ` can be followed by multiple ` REDUCE ` operations for different aggregations.
114+
39115``` sh
40116FT.AGGREGATE products " *"
41117 GROUPBY 1 @category
@@ -46,30 +122,34 @@ FT.AGGREGATE products "*"
46122 LIMIT 0 10
47123```
48124
49- ## Using multiple APPLY, GROUPBY, and REDUCE
125+ ## Multiple APPLY operations followed by GROUPBY and REDUCE
50126
51127` APPLY ` can be used in various ways before and after ` GROUPBY ` and ` REDUCE ` .
128+
52129``` sh
53130FT.AGGREGATE products " *"
54- APPLY " @price - @discount AS final_price"
55- APPLY " @final_price * @quantity AS total_revenue"
131+ LOAD 3 @price @discount @quantity
132+ APPLY " @price - @discount" AS final_price
133+ APPLY " @final_price * @quantity" AS total_revenue
56134 GROUPBY 1 @category
57- REDUCE SUM 1 total_revenue AS total_category_revenue
58- SORTBY 2 total_category_revenue DESC
135+ REDUCE SUM 1 @ total_revenue AS total_category_revenue
136+ SORTBY 2 @ total_category_revenue DESC
59137 LIMIT 0 10
60138```
61139
62- ## Using FILTER and PARAMS
140+ ## FILTER and PARAMS
63141
64142` FILTER ` is used to remove unwanted records, while ` PARAMS ` allows parameterized queries.
143+
65144``` sh
66145FT.AGGREGATE products " *"
67- PARAMS 2 " min_price " 500 " min_rating " 4.0
68- FILTER " @price >= $min_price "
69- FILTER " @rating >= $min_rating "
70- APPLY " @price * @quantity AS total_value"
71- SORTBY 2 total_value DESC
146+ LOAD 3 @price @rating @quantity
147+ FILTER " @price >= 500 "
148+ FILTER " @rating >= 4.0 "
149+ APPLY " @price * @quantity" AS total_value
150+ SORTBY 2 @ total_value DESC
72151 LIMIT 0 10
152+ DIALECT 2
73153```
74154
75155## Placement of FILTER before and after GROUPBY/APPLY
@@ -79,47 +159,35 @@ FT.AGGREGATE products "*"
79159- ** Before APPLY:** Ensures calculations are applied only to certain records.
80160- ** After APPLY:** Filters computed values.
81161
82- ## Using LOAD after GROUPBY/REDUCE
162+ ## LOAD after GROUPBY/REDUCE
83163
84- ` LOAD ` is generally used ** before** ` GROUPBY ` , but in some cases, it can be used afterward to retrieve document metadata.
85- ``` sh
86- FT.AGGREGATE products " *"
87- GROUPBY 1 @category
88- REDUCE COUNT 0 AS product_count
89- REDUCE SUM 1 @price AS total_price
90- WITHCURSOR COUNT 5
91- ```
164+ This is not allowed and you'll get a syntax error.
92165
93166## Placement rules for specific parameters
94167
95- | Parameter | Placement |
96- | ----------- | ---------------- |
97- | ` TIMEOUT ` | Can be placed anywhere |
98- | ` LIMIT ` | Must be at the end |
99- | ` WITHCURSOR ` | Must be at the end |
100- | ` SCORER ` | Can be placed anywhere |
101- | ` ADDSCORES ` | Must be before sorting |
102- | ` DIALECT ` | Must be at the end |
168+ | Parameter | Placement |
169+ | ----- | ----- |
170+ | ` TIMEOUT ` | Can be placed anywhere. |
171+ | ` LIMIT ` | Must be at the end, before ` DIALECT ` . |
172+ | ` WITHCURSOR ` | Must be at the end, before ` DIALECT ` . |
173+ | ` SCORER ` | Can be placed anywhere. |
174+ | ` ADDSCORES ` | Must be before sorting. |
175+ | ` DIALECT ` | Must be at the end. |
103176
104- ## LIMIT and WITHCURSOR are mutually exclusive
177+ ## LIMIT and WITHCURSOR used together
178+
179+ In practical terms, ` LIMIT ` and ` WITHCURSOR ` are mutually exclusive. However, they can be used together.
180+ ` LIMIT ` returns immediate results, while ` WITHCURSOR ` retrieves results incrementally using the [ cursor API] ({{< relref "/develop/interact/search-and-query/advanced-concepts/aggregations/#cursor-api" >}}).
105181
106- ` LIMIT ` returns immediate results, while ` WITHCURSOR ` retrieves results incrementally.
107182``` sh
108183FT.AGGREGATE products " *"
109184 GROUPBY 1 @category
110185 REDUCE COUNT 0 AS product_count
111- WITHCURSOR COUNT 5
186+ LIMIT 0 100
187+ WITHCURSOR COUNT 3
112188```
113189
114- ## Summary
115-
116- - ` GROUPBY ` allows multiple ` REDUCE ` functions.
117- - ` APPLY ` can be positioned before or after grouping.
118- - ` FILTER ` placement affects results significantly.
119- - ` LOAD ` after ` GROUPBY ` is only useful in specific cases.
120- - ` LIMIT ` and ` WITHCURSOR ` ** cannot** be used together.
190+ See the following resources for more information:
121191
122- For further reference:
123192- [ ` FT.AGGREGATE ` command page] ( https://redis.io/docs/latest/commands/ft.aggregate/ )
124193- [ RQE source code] ( https://github.com/RediSearch/RediSearch/tree/master/src/aggregate )
125-
0 commit comments