Both FT.AGGREGATE examples tell the reader to set `UnstableResp3: true` to use RESP3: example/search-aggregate-steps/README.md:15-17 example/search-aggregate-collect/README.md:15-18 That advice is stale in two ways. `Options.UnstableResp3` is deprecated and documented as a no-op (`options.go:448-451`, and the same note on `universal.go`, `osscluster.go`, `ring.go`, `sentinel.go`); README.md:536-543 says plainly that "new code should not set it". Grepping the package shows the field is only ever copied between option structs (`universal.go:291`, `osscluster.go:514`, `ring.go:276`, `sentinel.go:255`) or assigned from a URL (`sentinel.go:507`) — nothing reads it, so following the advice would change nothing. The stated reason is also gone: RediSearch RESP3 parsing has been stable since v9.20, which is why no flag is needed. The examples still construct their client with `Protocol: 2` (`search-aggregate-steps/main.go:25`, `search-aggregate-collect/main.go:29`); that choice is left alone, only the justification is corrected.
FT.AGGREGATE COLLECT reducer example
This example demonstrates the COLLECT reducer for FT.AGGREGATE: a
GROUPBY reducer that, within each group, projects a chosen set of fields
from every row — optionally deduplicated, sorted and limited — and returns
them as an array of per-entry maps under the reducer alias. A single
aggregation can therefore return each group and its top-N members.
Prerequisites
Redis 8.8+ with the Search module, listening on localhost:6379. COLLECT is
gated behind unstable search features; the example enables the gate itself
with CONFIG SET search-enable-unstable-features yes.
The client is configured with Protocol: 2. RESP3 needs no extra flag for
FT.AGGREGATE: its response is parsed into the same typed results on both
protocols. AggregateRow.Collect decodes both the RESP2 and RESP3 entry
shapes, so no other code changes are needed.
Run
go run .
The example:
- Creates an index
idx:productsover hashes prefixed withproduct:. - Seeds 10 products with
name,category,brand,price,rating. - Runs two aggregations:
- Top-2 per category (options struct) —
GROUPBY @categorywithREDUCE COLLECT ... FIELDS 2 @name @price SORTBY 2 @rating DESC LIMIT 0 2, built withredis.NewCollectReducernext to a plainCOUNTreducer. - Whole documents per brand (builder) —
LOAD *→GROUPBY @brand→COLLECT FIELDS *, expressed with the fluentAggregateBuilder.Collect. (On current unstable server builds,SORTBYcombined withFIELDS *drops the sort field from the entries — sort with an explicit field list instead, as in the first query.)
- Top-2 per category (options struct) —
Replies are decoded with AggregateRow.Collect, which returns the collected
entries as []map[string]interface{} regardless of protocol.