@@ -39,12 +39,13 @@ To install node-redis, simply:
39
39
npm install redis
40
40
```
41
41
42
- > "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.
42
+ > "redis" is the "whole in one" package that includes all the other packages. If you only need a subset of the commands,
43
+ > you can install the individual packages. See the list below.
43
44
44
45
## Packages
45
46
46
47
| Name | Description |
47
- | ------------------------------------------------ | --------------------------------------------------------------------------------------------- |
48
+ | ---------------------------------------------- | ------------------------------------------------------------------------------------------- |
48
49
| [ ` redis ` ] ( ./packages/redis ) | The client with all the [ "redis-stack"] ( https://github.com/redis-stack/redis-stack ) modules |
49
50
| [ ` @redis/client ` ] ( ./packages/client ) | The base clients (i.e ` RedisClient ` , ` RedisCluster ` , etc.) |
50
51
| [ ` @redis/bloom ` ] ( ./packages/bloom ) | [ Redis Bloom] ( https://redis.io/docs/data-types/probabilistic/ ) commands |
@@ -53,7 +54,340 @@ npm install redis
53
54
| [ ` @redis/time-series ` ] ( ./packages/time-series ) | [ Redis Time-Series] ( https://redis.io/docs/data-types/timeseries/ ) commands |
54
55
| [ ` @redis/entraid ` ] ( ./packages/entraid ) | Secure token-based authentication for Redis clients using Microsoft Entra ID |
55
56
56
- > Looking for a high-level library to handle object mapping? See [ redis-om-node] ( https://github.com/redis/redis-om-node ) !
57
+ > Looking for a high-level library to handle object mapping?
58
+ > See [ redis-om-node] ( https://github.com/redis/redis-om-node ) !
59
+
60
+ ## Installation
61
+
62
+ Start a redis via docker:
63
+
64
+ ``` bash
65
+ docker run -p 6379:6379 -d redis:8.0-rc1
66
+ ```
67
+
68
+ To install node-redis, simply:
69
+
70
+ ``` bash
71
+ npm install redis
72
+ ```
73
+
74
+ ## Usage
75
+
76
+ ### Basic Example
77
+
78
+ ``` typescript
79
+ import { createClient } from " redis" ;
80
+
81
+ const client = await createClient ()
82
+ .on (" error" , (err ) => console .log (" Redis Client Error" , err ))
83
+ .connect ();
84
+
85
+ await client .set (" key" , " value" );
86
+ const value = await client .get (" key" );
87
+ client .destroy ();
88
+ ```
89
+
90
+ The above code connects to localhost on port 6379. To connect to a different host or port, use a connection string in
91
+ the format ` redis[s]://[[username][:password]@][host][:port][/db-number] ` :
92
+
93
+ ``` typescript
94
+ createClient ({
95
+ url: " redis://alice:foobared@awesome.redis.server:6380" ,
96
+ });
97
+ ```
98
+
99
+ You can also use discrete parameters, UNIX sockets, and even TLS to connect. Details can be found in
100
+ the [ client configuration guide] ( ./docs/client-configuration.md ) .
101
+
102
+ To check if the the client is connected and ready to send commands, use ` client.isReady ` which returns a boolean.
103
+ ` client.isOpen ` is also available. This returns ` true ` when the client's underlying socket is open, and ` false ` when it
104
+ isn't (for example when the client is still connecting or reconnecting after a network error).
105
+
106
+ ### Redis Commands
107
+
108
+ There is built-in support for all of the [ out-of-the-box Redis commands] ( https://redis.io/commands ) . They are exposed
109
+ using the raw Redis command names (` HSET ` , ` HGETALL ` , etc.) and a friendlier camel-cased version (` hSet ` , ` hGetAll ` ,
110
+ etc.):
111
+
112
+ ``` typescript
113
+ // raw Redis commands
114
+ await client .HSET (" key" , " field" , " value" );
115
+ await client .HGETALL (" key" );
116
+
117
+ // friendly JavaScript commands
118
+ await client .hSet (" key" , " field" , " value" );
119
+ await client .hGetAll (" key" );
120
+ ```
121
+
122
+ Modifiers to commands are specified using a JavaScript object:
123
+
124
+ ``` typescript
125
+ await client .set (" key" , " value" , {
126
+ EX: 10 ,
127
+ NX: true ,
128
+ });
129
+ ```
130
+
131
+ Replies will be transformed into useful data structures:
132
+
133
+ ``` typescript
134
+ await client .hGetAll (" key" ); // { field1: 'value1', field2: 'value2' }
135
+ await client .hVals (" key" ); // ['value1', 'value2']
136
+ ```
137
+
138
+ ` Buffer ` s are supported as well:
139
+
140
+ ``` typescript
141
+ await client .hSet (" key" , " field" , Buffer .from (" value" )); // 'OK'
142
+ await client .hGetAll (commandOptions ({ returnBuffers: true }), " key" ); // { field: <Buffer 76 61 6c 75 65> }
143
+ ```
144
+
145
+ ### Unsupported Redis Commands
146
+
147
+ If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use ` .sendCommand() ` :
148
+
149
+ ``` typescript
150
+ await client .sendCommand ([" SET" , " key" , " value" , " NX" ]); // 'OK'
151
+
152
+ await client .sendCommand ([" HGETALL" , " key" ]); // ['key1', 'field1', 'key2', 'field2']
153
+ ```
154
+
155
+ ### Transactions (Multi/Exec)
156
+
157
+ Start a [ transaction] ( https://redis.io/topics/transactions ) by calling ` .multi() ` , then chaining your commands. When
158
+ you're done, call ` .exec() ` and you'll get an array back with your results:
159
+
160
+ ``` typescript
161
+ await client .set (" another-key" , " another-value" );
162
+
163
+ const [setKeyReply, otherKeyValue] = await client
164
+ .multi ()
165
+ .set (" key" , " value" )
166
+ .get (" another-key" )
167
+ .exec (); // ['OK', 'another-value']
168
+ ```
169
+
170
+ You can also [ watch] ( https://redis.io/topics/transactions#optimistic-locking-using-check-and-set ) keys by calling
171
+ ` .watch() ` . Your transaction will abort if any of the watched keys change.
172
+
173
+
174
+ ### Blocking Commands
175
+
176
+ In v4, ` RedisClient ` had the ability to create a pool of connections using an "Isolation Pool" on top of the "main"
177
+ connection. However, there was no way to use the pool without a "main" connection:
178
+
179
+ ``` javascript
180
+ const client = await createClient ()
181
+ .on (" error" , (err ) => console .error (err))
182
+ .connect ();
183
+
184
+ await client .ping (client .commandOptions ({ isolated: true }));
185
+ ```
186
+
187
+ In v5 we've extracted this pool logic into its own class—` RedisClientPool ` :
188
+
189
+ ``` javascript
190
+ const pool = await createClientPool ()
191
+ .on (" error" , (err ) => console .error (err))
192
+ .connect ();
193
+
194
+ await pool .ping ();
195
+ ```
196
+
197
+ To learn more about isolated execution, check out the [ guide] ( ./docs/isolated-execution.md ) .
198
+
199
+ ### Pub/Sub
200
+
201
+ See the [ Pub/Sub overview] ( ./docs/pub-sub.md ) .
202
+
203
+ ### Scan Iterator
204
+
205
+ [ ` SCAN ` ] ( https://redis.io/commands/scan ) results can be looped over
206
+ using [ async iterators] ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator ) :
207
+
208
+ ``` typescript
209
+ for await (const key of client .scanIterator ()) {
210
+ // use the key!
211
+ await client .get (key );
212
+ }
213
+ ```
214
+
215
+ This works with ` HSCAN ` , ` SSCAN ` , and ` ZSCAN ` too:
216
+
217
+ ``` typescript
218
+ for await (const { field, value } of client .hScanIterator (" hash" )) {
219
+ }
220
+ for await (const member of client .sScanIterator (" set" )) {
221
+ }
222
+ for await (const { score, value } of client .zScanIterator (" sorted-set" )) {
223
+ }
224
+ ```
225
+
226
+ You can override the default options by providing a configuration object:
227
+
228
+ ``` typescript
229
+ client .scanIterator ({
230
+ TYPE: " string" , // `SCAN` only
231
+ MATCH: " patter*" ,
232
+ COUNT: 100 ,
233
+ });
234
+ ```
235
+
236
+ ### [ Programmability] ( https://redis.io/docs/manual/programmability/ )
237
+
238
+ Redis provides a programming interface allowing code execution on the redis server.
239
+
240
+ #### [ Functions] ( https://redis.io/docs/manual/programmability/functions-intro/ )
241
+
242
+ The following example retrieves a key in redis, returning the value of the key, incremented by an integer. For example,
243
+ if your key _ foo_ has the value _ 17_ and we run ` add('foo', 25) ` , it returns the answer to Life, the Universe and
244
+ Everything.
245
+
246
+ ``` lua
247
+ # !lua name = library
248
+
249
+ redis .register_function {
250
+ function_name = ' add' ,
251
+ callback = function (keys , args ) return redis .call (' GET' , keys [1 ]) + args [1 ] end ,
252
+ flags = { ' no-writes' }
253
+ }
254
+ ```
255
+
256
+ Here is the same example, but in a format that can be pasted into the ` redis-cli ` .
257
+
258
+ ```
259
+ FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name=\"add\", callback=function(keys, args) return redis.call('GET', keys[1])+args[1] end, flags={\"no-writes\"}}"
260
+ ```
261
+
262
+ Load the prior redis function on the _ redis server_ before running the example below.
263
+
264
+ ``` typescript
265
+ import { createClient } from " redis" ;
266
+
267
+ const client = createClient ({
268
+ functions: {
269
+ library: {
270
+ add: {
271
+ NUMBER_OF_KEYS: 1 ,
272
+ transformArguments(key : string , toAdd : number ): Array <string > {
273
+ return [key , toAdd .toString ()];
274
+ },
275
+ transformReply(reply : number ): number {
276
+ return reply ;
277
+ },
278
+ },
279
+ },
280
+ },
281
+ });
282
+
283
+ await client .connect ();
284
+
285
+ await client .set (" key" , " 1" );
286
+ await client .library .add (" key" , 2 ); // 3
287
+ ```
288
+
289
+ #### [ Lua Scripts] ( https://redis.io/docs/manual/programmability/eval-intro/ )
290
+
291
+ The following is an end-to-end example of the prior concept.
292
+
293
+ ``` typescript
294
+ import { createClient , defineScript } from " redis" ;
295
+
296
+ const client = createClient ({
297
+ scripts: {
298
+ add: defineScript ({
299
+ NUMBER_OF_KEYS: 1 ,
300
+ SCRIPT: ' return redis.call("GET", KEYS[1]) + ARGV[1];' ,
301
+ transformArguments(key : string , toAdd : number ): Array <string > {
302
+ return [key , toAdd .toString ()];
303
+ },
304
+ transformReply(reply : number ): number {
305
+ return reply ;
306
+ },
307
+ }),
308
+ },
309
+ });
310
+
311
+ await client .connect ();
312
+
313
+ await client .set (" key" , " 1" );
314
+ await client .add (" key" , 2 ); // 3
315
+ ```
316
+
317
+ ### Disconnecting
318
+
319
+ The ` QUIT ` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Instead
320
+ of sending a ` QUIT ` command to the server, the client can simply close the network connection.
321
+
322
+ ` client.QUIT/quit() ` is replaced by ` client.close() ` . and, to avoid confusion, ` client.disconnect() ` has been renamed to
323
+ ` client.destroy() ` .
324
+
325
+ ``` typescript
326
+ client .destroy ();
327
+ ```
328
+
329
+ ### Auto-Pipelining
330
+
331
+ Node Redis will automatically pipeline requests that are made during the same "tick".
332
+
333
+ ``` typescript
334
+ client .set (" Tm9kZSBSZWRpcw==" , " users:1" );
335
+ client .sAdd (" users:1:tokens" , " Tm9kZSBSZWRpcw==" );
336
+ ```
337
+
338
+ Of course, if you don't do something with your Promises you're certain to
339
+ get [ unhandled Promise exceptions] ( https://nodejs.org/api/process.html#process_event_unhandledrejection ) . To take
340
+ advantage of auto-pipelining and handle your Promises, use ` Promise.all() ` .
341
+
342
+ ``` typescript
343
+ await Promise .all ([
344
+ client .set (" Tm9kZSBSZWRpcw==" , " users:1" ),
345
+ client .sAdd (" users:1:tokens" , " Tm9kZSBSZWRpcw==" ),
346
+ ]);
347
+ ```
348
+
349
+ ### Clustering
350
+
351
+ Check out the [ Clustering Guide] ( ./docs/clustering.md ) when using Node Redis to connect to a Redis Cluster.
352
+
353
+ ### Events
354
+
355
+ The Node Redis client class is an Nodejs EventEmitter and it emits an event each time the network status changes:
356
+
357
+ | Name | When | Listener arguments |
358
+ | ----------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------- |
359
+ | ` connect ` | Initiating a connection to the server | _ No arguments_ |
360
+ | ` ready ` | Client is ready to use | _ No arguments_ |
361
+ | ` end ` | Connection has been closed (via ` .disconnect() ` ) | _ No arguments_ |
362
+ | ` error ` | An error has occurred—usually a network issue such as "Socket closed unexpectedly" | ` (error: Error) ` |
363
+ | ` reconnecting ` | Client is trying to reconnect to the server | _ No arguments_ |
364
+ | ` sharded-channel-moved ` | See [ here] ( ./docs/pub-sub.md#sharded-channel-moved-event ) | See [ here] ( ./docs/pub-sub.md#sharded-channel-moved-event ) |
365
+
366
+ > :warning : You ** MUST** listen to ` error ` events. If a client doesn't have at least one ` error ` listener registered and
367
+ > 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.
368
+
369
+ > The client will not emit [ any other events] ( ./docs/v3-to-v4.md#all-the-removed-events ) beyond those listed above.
370
+
371
+ ## Supported Redis versions
372
+
373
+ Node Redis is supported with the following versions of Redis:
374
+
375
+ | Version | Supported |
376
+ | ------- | ------------------ |
377
+ | 8.0.z | :heavy_check_mark : |
378
+ | 7.0.z | :heavy_check_mark : |
379
+ | 6.2.z | :heavy_check_mark : |
380
+ | 6.0.z | :heavy_check_mark : |
381
+ | 5.0.z | :heavy_check_mark : |
382
+ | < 5.0 | :x : |
383
+
384
+ > Node Redis should work with older versions of Redis, but it is not fully tested and we cannot offer support.
385
+
386
+ ## Migration
387
+
388
+ - [ From V3 to V4] ( docs/v3-to-v4.md )
389
+ - [ From V4 to V5] ( docs/v4-to-v5.md )
390
+ - [ V5] ( docs/v5.md )
57
391
58
392
## Contributing
59
393
0 commit comments