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