@@ -39,12 +39,13 @@ To install node-redis, simply:
3939npm install redis
4040```
4141
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.
4344
4445## Packages
4546
4647| Name | Description |
47- | ------------------------------------------------ | --------------------------------------------------------------------------------------------- |
48+ | ---------------------------------------------- | ------------------------------------------------------------------------------------------- |
4849| [ ` redis ` ] ( ./packages/redis ) | The client with all the [ "redis-stack"] ( https://github.com/redis-stack/redis-stack ) modules |
4950| [ ` @redis/client ` ] ( ./packages/client ) | The base clients (i.e ` RedisClient ` , ` RedisCluster ` , etc.) |
5051| [ ` @redis/bloom ` ] ( ./packages/bloom ) | [ Redis Bloom] ( https://redis.io/docs/data-types/probabilistic/ ) commands |
@@ -53,7 +54,340 @@ npm install redis
5354| [ ` @redis/time-series ` ] ( ./packages/time-series ) | [ Redis Time-Series] ( https://redis.io/docs/data-types/timeseries/ ) commands |
5455| [ ` @redis/entraid ` ] ( ./packages/entraid ) | Secure token-based authentication for Redis clients using Microsoft Entra ID |
5556
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:[email protected] :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 )
57391
58392## Contributing
59393
0 commit comments