Modules
Use typed JSON, Search, TimeSeries, probabilistic and vector commands on servers that have the modules.
The Redis service has typed commands for the optional server modules: JSON, Search, TimeSeries, the probabilistic structures (Bloom, Cuckoo, Count-Min, Top-K, t-digest) and vector sets. They work only on a server that has the module loaded. The client does not check, so a missing module comes back as a ServerError.
Example (Storing and Reading a JSON Document)
import { } from "effect";
import { PayloadCodec, } from "@effect-kit/redis";
export const = .(function* () {
const = yield* ;
yield* .("user:42", "$", '{"name":"Ada","visits":1}');
return yield* .("user:42", PayloadCodec.);
});jsonSet takes the document as text and returns a boolean. jsonGet returns the bytes and jsonGetWith decodes them with a PayloadCodec. Nothing is converted to JSON for you.
Searching and vectors
ftCreate defines an index and ftSearch queries it. encodeFloat32 builds the binary blob a vector field expects.
Example (Creating a Vector Index and Querying It)
import { } from "effect";
import { , } from "@effect-kit/redis";
export const = .(function* () {
const = yield* ;
yield* .(
"idx:docs",
[
{ : "title", : "TEXT" },
{
: "embedding",
: "VECTOR",
: "HNSW",
: { : "FLOAT32", : 2, : "COSINE" },
},
],
{ : "HASH", : ["doc:"] },
);
yield* .("doc:one", [
["title", "hello world"],
["embedding", yield* ([1, 0])],
]);
return yield* .("idx:docs", "hello", { : 2 });
});Indexing is asynchronous on the server. A document written a moment ago may not be searchable yet.
ftSearch returns total and a list of documents. Each document has an id and optional fields.
Aggregating with a cursor
RedisSearch.aggregate returns a Stream of rows and reads an aggregation through a server cursor. One leased session owns the cursor, reads the pages and deletes it, including when you stop reading early. RedisSearch is not in the runtime layer, so add it with RedisSearch.layer, which needs RedisSessions.
Example (Providing RedisSearch)
import { , , } from "effect";
import { } from "@effect-kit/redis";
import { } from "@effect-kit/redis/node";
const = .({ : "redis://localhost:6379" });
const = ..(.());
export const = .(function* () {
const = yield* ;
return yield*
.("idx:docs", "hello", { : [{ : "Load", : [{ : "@title" }] }] })
.(.(10), .);
}).(.());Declaring modules in a profile
A profile with modules rejects commands from any module not in the list, before sending. Use it to catch a missing module in development.
Example (Allowing Only JSON)
import { RedisProfiles } from "@effect-kit/redis";
import { } from "@effect-kit/redis/node";
export const = .({
: "redis://localhost:6379",
: RedisProfiles.({ : ["json"] }),
});A search command now fails with ProfileError and reason: "module". The profile module names are json, search, timeseries, probabilistic, vectors, upstash-search and upstash-vector.
Cluster and modules
In a cluster, keep the keys of one command in one slot with a hash tag, as in Multi-key commands. Commands without a key, such as ftList and tsMget, fail with ClusterError and reason: "explicit-target-required". Run them on a node with cluster.node(id).
Tested module configurations
| Fixture | Server | Modules |
|---|---|---|
redis-modules | Redis 8.10.2 | JSON, Search, TimeSeries, Bloom, vector sets |
redis-stack | Redis Stack server image 7.4.0-v8 | JSON, Search, TimeSeries, Bloom |
valkey-modules | Valkey bundle image 9.1.3 | JSON, Search, Bloom |
Dragonfly, KeyDB, Redict, Garnet and Kvrocks are tested with no modules. On Upstash over HTTP, use redis.upstash.searchQuery and redis.upstash.vectorQuery instead; see Upstash.
Search behavior differs between products. For example, withScores is rejected by the Valkey bundle in the package tests.