You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-09 00:22:08 +03:00
Update README.MD (#2924)
* Update README.MD * docs: update programmability.md examples + add Programmability section to README and * fix imports according to the new v5 exports * more v5 docs updates --------- Co-authored-by: Nikolay Karadzhov <nkaradzhov89@gmail.com>
This commit is contained in:
259
README.md
259
README.md
@@ -27,10 +27,10 @@ node-redis is a modern, high performance [Redis](https://redis.io) client for No
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Start a redis-server via docker (or any other method you prefer):
|
Start a redis via docker:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -p 6379:6379 -it redis/redis-stack-server:latest
|
docker run -p 6379:6379 -d redis:8.0-rc1
|
||||||
```
|
```
|
||||||
|
|
||||||
To install node-redis, simply:
|
To install node-redis, simply:
|
||||||
@@ -38,13 +38,13 @@ To install node-redis, simply:
|
|||||||
```bash
|
```bash
|
||||||
npm install redis
|
npm install redis
|
||||||
```
|
```
|
||||||
|
> "redis" is the "whole in one" package that includes all the other packages. If you only need a subset of the commands,
|
||||||
> "redis" is the "whole in one" package that includes all the other packages. If you only need a subset of the commands, you can install the individual packages. See the list below.
|
> you can install the individual packages. See the list below.
|
||||||
|
|
||||||
## Packages
|
## Packages
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|------------------------------------------------|---------------------------------------------------------------------------------------------|
|
| ---------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
||||||
| [`redis`](./packages/redis) | The client with all the ["redis-stack"](https://github.com/redis-stack/redis-stack) modules |
|
| [`redis`](./packages/redis) | The client with all the ["redis-stack"](https://github.com/redis-stack/redis-stack) modules |
|
||||||
| [`@redis/client`](./packages/client) | The base clients (i.e `RedisClient`, `RedisCluster`, etc.) |
|
| [`@redis/client`](./packages/client) | The base clients (i.e `RedisClient`, `RedisCluster`, etc.) |
|
||||||
| [`@redis/bloom`](./packages/bloom) | [Redis Bloom](https://redis.io/docs/data-types/probabilistic/) commands |
|
| [`@redis/bloom`](./packages/bloom) | [Redis Bloom](https://redis.io/docs/data-types/probabilistic/) commands |
|
||||||
@@ -53,7 +53,254 @@ npm install redis
|
|||||||
| [`@redis/time-series`](./packages/time-series) | [Redis Time-Series](https://redis.io/docs/data-types/timeseries/) commands |
|
| [`@redis/time-series`](./packages/time-series) | [Redis Time-Series](https://redis.io/docs/data-types/timeseries/) commands |
|
||||||
| [`@redis/entraid`](./packages/entraid) | Secure token-based authentication for Redis clients using Microsoft Entra ID |
|
| [`@redis/entraid`](./packages/entraid) | Secure token-based authentication for Redis clients using Microsoft Entra ID |
|
||||||
|
|
||||||
> Looking for a high-level library to handle object mapping? See [redis-om-node](https://github.com/redis/redis-om-node)!
|
> Looking for a high-level library to handle object mapping?
|
||||||
|
> See [redis-om-node](https://github.com/redis/redis-om-node)!
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic Example
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createClient } from "redis";
|
||||||
|
|
||||||
|
const client = await createClient()
|
||||||
|
.on("error", (err) => console.log("Redis Client Error", err))
|
||||||
|
.connect();
|
||||||
|
|
||||||
|
await client.set("key", "value");
|
||||||
|
const value = await client.get("key");
|
||||||
|
client.destroy();
|
||||||
|
```
|
||||||
|
|
||||||
|
The above code connects to localhost on port 6379. To connect to a different host or port, use a connection string in
|
||||||
|
the format `redis[s]://[[username][:password]@][host][:port][/db-number]`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
createClient({
|
||||||
|
url: "redis://alice:foobared@awesome.redis.server:6380",
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use discrete parameters, UNIX sockets, and even TLS to connect. Details can be found in
|
||||||
|
the [client configuration guide](./docs/client-configuration.md).
|
||||||
|
|
||||||
|
To check if the the client is connected and ready to send commands, use `client.isReady` which returns a boolean.
|
||||||
|
`client.isOpen` is also available. This returns `true` when the client's underlying socket is open, and `false` when it
|
||||||
|
isn't (for example when the client is still connecting or reconnecting after a network error).
|
||||||
|
|
||||||
|
### Redis Commands
|
||||||
|
|
||||||
|
There is built-in support for all of the [out-of-the-box Redis commands](https://redis.io/commands). They are exposed
|
||||||
|
using the raw Redis command names (`HSET`, `HGETALL`, etc.) and a friendlier camel-cased version (`hSet`, `hGetAll`,
|
||||||
|
etc.):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// raw Redis commands
|
||||||
|
await client.HSET("key", "field", "value");
|
||||||
|
await client.HGETALL("key");
|
||||||
|
|
||||||
|
// friendly JavaScript commands
|
||||||
|
await client.hSet("key", "field", "value");
|
||||||
|
await client.hGetAll("key");
|
||||||
|
```
|
||||||
|
|
||||||
|
Modifiers to commands are specified using a JavaScript object:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await client.set("key", "value", {
|
||||||
|
EX: 10,
|
||||||
|
NX: true,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Replies will be transformed into useful data structures:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await client.hGetAll("key"); // { field1: 'value1', field2: 'value2' }
|
||||||
|
await client.hVals("key"); // ['value1', 'value2']
|
||||||
|
```
|
||||||
|
|
||||||
|
`Buffer`s are supported as well:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const client = createClient().withTypeMapping({
|
||||||
|
[RESP_TYPES.BLOB_STRING]: Buffer
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.hSet("key", "field", Buffer.from("value")); // 'OK'
|
||||||
|
await client.hGet("key", "field"); // { field: <Buffer 76 61 6c 75 65> }
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unsupported Redis Commands
|
||||||
|
|
||||||
|
If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use `.sendCommand()`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await client.sendCommand(["SET", "key", "value", "NX"]); // 'OK'
|
||||||
|
|
||||||
|
await client.sendCommand(["HGETALL", "key"]); // ['key1', 'field1', 'key2', 'field2']
|
||||||
|
```
|
||||||
|
|
||||||
|
### Transactions (Multi/Exec)
|
||||||
|
|
||||||
|
Start a [transaction](https://redis.io/topics/transactions) by calling `.multi()`, then chaining your commands. When
|
||||||
|
you're done, call `.exec()` and you'll get an array back with your results:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await client.set("another-key", "another-value");
|
||||||
|
|
||||||
|
const [setKeyReply, otherKeyValue] = await client
|
||||||
|
.multi()
|
||||||
|
.set("key", "value")
|
||||||
|
.get("another-key")
|
||||||
|
.exec(); // ['OK', 'another-value']
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also [watch](https://redis.io/topics/transactions#optimistic-locking-using-check-and-set) keys by calling
|
||||||
|
`.watch()`. Your transaction will abort if any of the watched keys change.
|
||||||
|
|
||||||
|
|
||||||
|
### Blocking Commands
|
||||||
|
|
||||||
|
In v4, `RedisClient` had the ability to create a pool of connections using an "Isolation Pool" on top of the "main"
|
||||||
|
connection. However, there was no way to use the pool without a "main" connection:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const client = await createClient()
|
||||||
|
.on("error", (err) => console.error(err))
|
||||||
|
.connect();
|
||||||
|
|
||||||
|
await client.ping(client.commandOptions({ isolated: true }));
|
||||||
|
```
|
||||||
|
|
||||||
|
In v5 we've extracted this pool logic into its own class—`RedisClientPool`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const pool = await createClientPool()
|
||||||
|
.on("error", (err) => console.error(err))
|
||||||
|
.connect();
|
||||||
|
|
||||||
|
await pool.ping();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Pub/Sub
|
||||||
|
|
||||||
|
See the [Pub/Sub overview](./docs/pub-sub.md).
|
||||||
|
|
||||||
|
### Scan Iterator
|
||||||
|
|
||||||
|
[`SCAN`](https://redis.io/commands/scan) results can be looped over
|
||||||
|
using [async iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
for await (const key of client.scanIterator()) {
|
||||||
|
// use the key!
|
||||||
|
await client.get(key);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This works with `HSCAN`, `SSCAN`, and `ZSCAN` too:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
for await (const { field, value } of client.hScanIterator("hash")) {
|
||||||
|
}
|
||||||
|
for await (const member of client.sScanIterator("set")) {
|
||||||
|
}
|
||||||
|
for await (const { score, value } of client.zScanIterator("sorted-set")) {
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can override the default options by providing a configuration object:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
client.scanIterator({
|
||||||
|
TYPE: "string", // `SCAN` only
|
||||||
|
MATCH: "patter*",
|
||||||
|
COUNT: 100,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Disconnecting
|
||||||
|
|
||||||
|
The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Instead
|
||||||
|
of sending a `QUIT` command to the server, the client can simply close the network connection.
|
||||||
|
|
||||||
|
`client.QUIT/quit()` is replaced by `client.close()`. and, to avoid confusion, `client.disconnect()` has been renamed to
|
||||||
|
`client.destroy()`.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
client.destroy();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Auto-Pipelining
|
||||||
|
|
||||||
|
Node Redis will automatically pipeline requests that are made during the same "tick".
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
client.set("Tm9kZSBSZWRpcw==", "users:1");
|
||||||
|
client.sAdd("users:1:tokens", "Tm9kZSBSZWRpcw==");
|
||||||
|
```
|
||||||
|
|
||||||
|
Of course, if you don't do something with your Promises you're certain to
|
||||||
|
get [unhandled Promise exceptions](https://nodejs.org/api/process.html#process_event_unhandledrejection). To take
|
||||||
|
advantage of auto-pipelining and handle your Promises, use `Promise.all()`.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await Promise.all([
|
||||||
|
client.set("Tm9kZSBSZWRpcw==", "users:1"),
|
||||||
|
client.sAdd("users:1:tokens", "Tm9kZSBSZWRpcw=="),
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Programmability
|
||||||
|
|
||||||
|
See the [Programmability overview](./docs/programmability.md).
|
||||||
|
|
||||||
|
### Clustering
|
||||||
|
|
||||||
|
Check out the [Clustering Guide](./docs/clustering.md) when using Node Redis to connect to a Redis Cluster.
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
The Node Redis client class is an Nodejs EventEmitter and it emits an event each time the network status changes:
|
||||||
|
|
||||||
|
| Name | When | Listener arguments |
|
||||||
|
| ----------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------- |
|
||||||
|
| `connect` | Initiating a connection to the server | _No arguments_ |
|
||||||
|
| `ready` | Client is ready to use | _No arguments_ |
|
||||||
|
| `end` | Connection has been closed (via `.disconnect()`) | _No arguments_ |
|
||||||
|
| `error` | An error has occurred—usually a network issue such as "Socket closed unexpectedly" | `(error: Error)` |
|
||||||
|
| `reconnecting` | Client is trying to reconnect to the server | _No arguments_ |
|
||||||
|
| `sharded-channel-moved` | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | See [here](./docs/pub-sub.md#sharded-channel-moved-event) |
|
||||||
|
|
||||||
|
> :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and
|
||||||
|
> an `error` occurs, that error will be thrown and the Node.js process will exit. See the [ > `EventEmitter` docs](https://nodejs.org/api/events.html#events_error_events) for more details.
|
||||||
|
|
||||||
|
> The client will not emit [any other events](./docs/v3-to-v4.md#all-the-removed-events) beyond those listed above.
|
||||||
|
|
||||||
|
## Supported Redis versions
|
||||||
|
|
||||||
|
Node Redis is supported with the following versions of Redis:
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 8.0.z | :heavy_check_mark: |
|
||||||
|
| 7.0.z | :heavy_check_mark: |
|
||||||
|
| 6.2.z | :heavy_check_mark: |
|
||||||
|
| 6.0.z | :heavy_check_mark: |
|
||||||
|
| 5.0.z | :heavy_check_mark: |
|
||||||
|
| < 5.0 | :x: |
|
||||||
|
|
||||||
|
> Node Redis should work with older versions of Redis, but it is not fully tested and we cannot offer support.
|
||||||
|
|
||||||
|
## Migration
|
||||||
|
|
||||||
|
- [From V3 to V4](docs/v3-to-v4.md)
|
||||||
|
- [From V4 to V5](docs/v4-to-v5.md)
|
||||||
|
- [V5](docs/v5.md)
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ By default, each type is mapped to the first option in the lists below. To chang
|
|||||||
- Double (`,`) => `number | string`
|
- Double (`,`) => `number | string`
|
||||||
- Simple String (`+`) => `string | Buffer`
|
- Simple String (`+`) => `string | Buffer`
|
||||||
- Blob String (`$`) => `string | Buffer`
|
- Blob String (`$`) => `string | Buffer`
|
||||||
- Verbatim String (`=`) => `string | Buffer | VerbatimString` (TODO: `VerbatimString` typedoc link)
|
- Verbatim String (`=`) => `string | Buffer | VerbatimString`
|
||||||
- Simple Error (`-`) => `ErrorReply`
|
- Simple Error (`-`) => `ErrorReply`
|
||||||
- Blob Error (`!`) => `ErrorReply`
|
- Blob Error (`!`) => `ErrorReply`
|
||||||
- Array (`*`) => `Array`
|
- Array (`*`) => `Array`
|
||||||
|
@@ -25,16 +25,22 @@ FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name='add',
|
|||||||
Load the prior redis function on the _redis server_ before running the example below.
|
Load the prior redis function on the _redis server_ before running the example below.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { createClient } from 'redis';
|
import { CommandParser } from '@redis/client/lib/client/parser';
|
||||||
|
import { NumberReply } from '@redis/client/lib/RESP/types';
|
||||||
|
import { createClient, RedisArgument } from 'redis';
|
||||||
|
|
||||||
const client = createClient({
|
const client = createClient({
|
||||||
functions: {
|
functions: {
|
||||||
library: {
|
library: {
|
||||||
add: {
|
add: {
|
||||||
NUMBER_OF_KEYS: 1,
|
NUMBER_OF_KEYS: 1,
|
||||||
FIRST_KEY_INDEX: 1,
|
parseCommand(
|
||||||
transformArguments(key: string, toAdd: number): Array<string> {
|
parser: CommandParser,
|
||||||
return [key, toAdd.toString()];
|
key: RedisArgument,
|
||||||
|
toAdd: RedisArgument
|
||||||
|
) {
|
||||||
|
parser.pushKey(key)
|
||||||
|
parser.push(toAdd)
|
||||||
},
|
},
|
||||||
transformReply: undefined as unknown as () => NumberReply
|
transformReply: undefined as unknown as () => NumberReply
|
||||||
}
|
}
|
||||||
@@ -43,9 +49,8 @@ const client = createClient({
|
|||||||
});
|
});
|
||||||
|
|
||||||
await client.connect();
|
await client.connect();
|
||||||
|
|
||||||
await client.set('key', '1');
|
await client.set('key', '1');
|
||||||
await client.library.add('key', 2); // 3
|
await client.library.add('key', '2'); // 3
|
||||||
```
|
```
|
||||||
|
|
||||||
## [Lua Scripts](https://redis.io/docs/manual/programmability/eval-intro/)
|
## [Lua Scripts](https://redis.io/docs/manual/programmability/eval-intro/)
|
||||||
@@ -53,7 +58,9 @@ await client.library.add('key', 2); // 3
|
|||||||
The following is an end-to-end example of the prior concept.
|
The following is an end-to-end example of the prior concept.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { createClient, defineScript, NumberReply } from 'redis';
|
import { CommandParser } from '@redis/client/lib/client/parser';
|
||||||
|
import { NumberReply } from '@redis/client/lib/RESP/types';
|
||||||
|
import { createClient, defineScript, RedisArgument } from 'redis';
|
||||||
|
|
||||||
const client = createClient({
|
const client = createClient({
|
||||||
scripts: {
|
scripts: {
|
||||||
@@ -61,8 +68,13 @@ const client = createClient({
|
|||||||
SCRIPT: 'return redis.call("GET", KEYS[1]) + ARGV[1];',
|
SCRIPT: 'return redis.call("GET", KEYS[1]) + ARGV[1];',
|
||||||
NUMBER_OF_KEYS: 1,
|
NUMBER_OF_KEYS: 1,
|
||||||
FIRST_KEY_INDEX: 1,
|
FIRST_KEY_INDEX: 1,
|
||||||
transformArguments(key: string, toAdd: number): Array<string> {
|
parseCommand(
|
||||||
return [key, toAdd.toString()];
|
parser: CommandParser,
|
||||||
|
key: RedisArgument,
|
||||||
|
toAdd: RedisArgument
|
||||||
|
) {
|
||||||
|
parser.pushKey(key)
|
||||||
|
parser.push(toAdd)
|
||||||
},
|
},
|
||||||
transformReply: undefined as unknown as () => NumberReply
|
transformReply: undefined as unknown as () => NumberReply
|
||||||
})
|
})
|
||||||
@@ -70,7 +82,6 @@ const client = createClient({
|
|||||||
});
|
});
|
||||||
|
|
||||||
await client.connect();
|
await client.connect();
|
||||||
|
|
||||||
await client.set('key', '1');
|
await client.set('key', '1');
|
||||||
await client.add('key', 2); // 3
|
await client.add('key', '2'); // 3
|
||||||
```
|
```
|
||||||
|
@@ -234,12 +234,12 @@ In v5, any unwritten commands (in the same pipeline) will be discarded.
|
|||||||
### Time Series
|
### Time Series
|
||||||
|
|
||||||
- `TS.ADD`: `boolean` -> `number` [^boolean-to-number]
|
- `TS.ADD`: `boolean` -> `number` [^boolean-to-number]
|
||||||
- `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION`
|
- `TS.[M][REV]RANGE`: the `ALIGN` argument has been moved into `AGGREGATION`
|
||||||
- `TS.SYNUPDATE`: `Array<string | Array<string>>` -> `Record<string, Array<string>>`
|
- `TS.SYNUPDATE`: `Array<string | Array<string>>` -> `Record<string, Array<string>>`
|
||||||
- `TS.M[REV]RANGE[_WITHLABELS]`, `TS.MGET[_WITHLABELS]`: TODO
|
- `TimeSeriesDuplicatePolicies` -> `TIME_SERIES_DUPLICATE_POLICIES` [^enum-to-constants]
|
||||||
|
- `TimeSeriesEncoding` -> `TIME_SERIES_ENCODING` [^enum-to-constants]
|
||||||
[^enum-to-constants]: TODO
|
- `TimeSeriesAggregationType` -> `TIME_SERIES_AGGREGATION_TYPE` [^enum-to-constants]
|
||||||
|
- `TimeSeriesReducers` -> `TIME_SERIES_REDUCERS` [^enum-to-constants]
|
||||||
|
- `TimeSeriesBucketTimestamp` -> `TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants]
|
||||||
|
|
||||||
[^map-keys]: To avoid unnecessary transformations and confusion, map keys will not be transformed to "js friendly" names (i.e. `number-of-keys` will not be renamed to `numberOfKeys`). See [here](https://github.com/redis/node-redis/discussions/2506).
|
[^map-keys]: To avoid unnecessary transformations and confusion, map keys will not be transformed to "js friendly" names (i.e. `number-of-keys` will not be renamed to `numberOfKeys`). See [here](https://github.com/redis/node-redis/discussions/2506).
|
||||||
|
|
||||||
[^future-proofing]: TODO
|
|
||||||
|
65
docs/v5.md
65
docs/v5.md
@@ -1,30 +1,83 @@
|
|||||||
# RESP3 Support
|
# RESP3 Support
|
||||||
|
|
||||||
TODO
|
Node Redis v5 adds support for [RESP3](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md), the new Redis serialization protocol. RESP3 offers richer data types and improved type handling compared to RESP2.
|
||||||
|
|
||||||
|
To use RESP3, specify it when creating your client:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
import { createClient } from 'redis';
|
||||||
|
|
||||||
const client = createClient({
|
const client = createClient({
|
||||||
RESP: 3
|
RESP: 3
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Type Mapping
|
||||||
|
|
||||||
|
With RESP3, you can leverage the protocol's richer type system. You can customize how different Redis types are represented in JavaScript using type mapping:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// by default
|
import { createClient, RESP_TYPES } from 'redis';
|
||||||
|
|
||||||
|
// By default
|
||||||
await client.hGetAll('key'); // Record<string, string>
|
await client.hGetAll('key'); // Record<string, string>
|
||||||
|
|
||||||
|
// Use Map instead of plain object
|
||||||
await client.withTypeMapping({
|
await client.withTypeMapping({
|
||||||
[TYPES.MAP]: Map
|
[RESP_TYPES.MAP]: Map
|
||||||
}).hGetAll('key'); // Map<string, string>
|
}).hGetAll('key'); // Map<string, string>
|
||||||
|
|
||||||
|
// Use both Map and Buffer
|
||||||
await client.withTypeMapping({
|
await client.withTypeMapping({
|
||||||
[TYPES.MAP]: Map,
|
[RESP_TYPES.MAP]: Map,
|
||||||
[TYPES.BLOB_STRING]: Buffer
|
[RESP_TYPES.BLOB_STRING]: Buffer
|
||||||
}).hGetAll('key'); // Map<string, Buffer>
|
}).hGetAll('key'); // Map<string, Buffer>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This replaces the previous approach of using `commandOptions({ returnBuffers: true })` in v4.
|
||||||
|
|
||||||
|
## PubSub in RESP3
|
||||||
|
|
||||||
|
RESP3 uses a different mechanism for handling Pub/Sub messages. Instead of modifying the `onReply` handler as in RESP2, RESP3 provides a dedicated `onPush` handler. When using RESP3, the client automatically uses this more efficient push notification system.
|
||||||
|
|
||||||
|
## Known Limitations
|
||||||
|
|
||||||
|
### Unstable Module Commands
|
||||||
|
|
||||||
|
Some Redis module commands have unstable RESP3 transformations. These commands will throw an error when used with RESP3 unless you explicitly opt in to using them by setting `unstableResp3: true` in your client configuration:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const client = createClient({
|
||||||
|
RESP: 3,
|
||||||
|
unstableResp3: true
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The following commands have unstable RESP3 implementations:
|
||||||
|
|
||||||
|
1. **Stream Commands**:
|
||||||
|
- `XREAD` and `XREADGROUP` - The response format differs between RESP2 and RESP3
|
||||||
|
|
||||||
|
2. **Search Commands (RediSearch)**:
|
||||||
|
- `FT.AGGREGATE`
|
||||||
|
- `FT.AGGREGATE_WITHCURSOR`
|
||||||
|
- `FT.CURSOR_READ`
|
||||||
|
- `FT.INFO`
|
||||||
|
- `FT.PROFILE_AGGREGATE`
|
||||||
|
- `FT.PROFILE_SEARCH`
|
||||||
|
- `FT.SEARCH`
|
||||||
|
- `FT.SEARCH_NOCONTENT`
|
||||||
|
- `FT.SPELLCHECK`
|
||||||
|
|
||||||
|
3. **Time Series Commands**:
|
||||||
|
- `TS.INFO`
|
||||||
|
- `TS.INFO_DEBUG`
|
||||||
|
|
||||||
|
If you need to use these commands with RESP3, be aware that the response format might change in future versions.
|
||||||
|
|
||||||
# Sentinel Support
|
# Sentinel Support
|
||||||
|
|
||||||
[TODO](./sentinel.md)
|
[Sentinel](./sentinel.md)
|
||||||
|
|
||||||
# `multi.exec<'typed'>` / `multi.execTyped`
|
# `multi.exec<'typed'>` / `multi.execTyped`
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user