Upstash Redis Search can index the entries of a Redis stream. Each stream entry becomes a separate search document, so you can search event fields without scanning the stream or knowing an entry ID.
How stream indexes work#
A stream index differs from a JSON, hash, or string index in two ways:
- It is bound to one exact stream key instead of one or more key prefixes.
- Each stream entry is a document. The document ID returned by Search is the stream entry ID.
The fields added with XADD provide the document fields. Stream
payloads are flat field-value pairs, so schema fields refer to stream fields rather than nested paths.
The stream does not need to exist when you create the index. Entries added later are indexed automatically.
Create a stream index#
Use ON STREAM followed by the exact stream key. PREFIX is not supported for stream indexes.
Only one search index can be bound to a stream at a time. To bind the stream to a different index,
first drop the existing index with SEARCH.DROP.
Add and search entries#
Add entries with regular stream commands. The field names do not need to appear in the schema, but only schema fields are searchable.
The matching result has 1-0 as its document ID. Without NOCONTENT, its content is returned as the
stream entry's field-value pairs. All regular query features, including filtering, highlighting,
sorting, pagination, and score functions, use the fields declared in the schema.
Index updates are asynchronous. Use
SEARCH.WAITINDEXING when a query must include preceding
writes, especially in tests and setup scripts.
Schema values#
Redis stores stream field values as strings. Search converts each value according to its schema type:
U64,I64, andF64fields require values in the corresponding numeric format.BOOLfields accepttrueorfalse.DATEfields require an RFC 3339 timestamp, such as2026-08-24T09:30:00Z.TEXT,KEYWORD, andFACETfields use string values.
Missing fields and values that cannot be converted are omitted from the indexed document. If an entry has no valid schema fields, it is not added to the index.
You can use FROM to expose a stream field under a different index field name:
Queries use the schema name (description), while SELECT and returned content use the original
stream field name (message).
Existing entries and reindexing#
Creating an index scans entries already present in the stream. Use SKIPINITIALSCAN to index only new
entries at first:
Run SEARCH.REINDEX later to rebuild the index from all
entries currently in the stream.
Entry deletion and trimming#
The index follows the contents of the stream:
| Stream change | Search index change |
|---|---|
XADD | Adds a document for the new entry. Entries removed by an XADD trim are removed too. |
XDEL, XDELEX, or XACKDEL | Removes the documents for deleted entries. |
XTRIM | Removes the documents for trimmed entries. |
DEL, UNLINK, or expiration of the stream key | Removes all documents but keeps the index definition. |
If a deleted or expired stream is recreated under the same key, new entries are added to the existing
index. Consumer-group operations that do not change entry data, such as XACK, do not change the
index.
RENAME, RENAMENX, and COPY are not supported for stream keys.
Next steps#
- See Schema Definition for field types and options.
- See Querying and filtering for the JSON query syntax.
- See Aggregations to group and summarize stream entries.