Deno - Using Redis Examples

This tutorial shows you how to use redis in a Deno application.

Redis is an in-memory data structure store which can be used for caching, database, and message broker. It supports many data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. It also supports different levels of on-disk persistence, Redis Sentinal for high availability, Redis Cluster for automatic partitioning, and many other features. Redis is very popular and has libraries for many programming languages.

If you use Deno, below are the examples of how to use Redis in your Deno application using a third-party module named redis

Using redis Module

To be able to use redis, your application needs to connect to a redis server. Because the application needs to connect to the redis server, --allow-net flag is required while running deno run command. It would be better if you only allow network access for specific address. For example, if the redis server is on localhost on port 6379, you should add --allow-net=127.0.0.1:6379.

The function of the module we are going to use is connect. You need to import and re-export the function in deps.ts file.

deps.ts

  import {
    connect as redisConnect
  } from 'https://deno.land/x/redis/mod.ts';

  export { redisConnect };

Connecting to Redis Server

First you need to connect to the redis server. Below is the function you need to call.

  function connect(options: RedisConnectOptions): Promise<Redis>

The function returns an instance of redis client. Having created the instance, you can use the functions provided by the module, such as set, get, del. This tutorial only gives examples for some of frequently used operations. To get the list of available functions, you can read the source code.

To call the function, you need to pass an argument whose type is RedisConnectOptions, which has the following fields.

  • hostname: string: Host of the redis server.
  • port?: number | string: Port of the redis server.
  • tls?: boolean: Whether to use TLS.
  • db?: number: The database index.
  • password?: string: Password of the redis server.
  • name?: string: The connection name.
  • maxRetryCount?: number: Maximum number of retries to connect.
  • retryInterval?: number: Interval between retry in milliseconds.

The only required field is hostname, but you may also need to pass other fields based on your needs.

In an application, you may need to perform redis operations in multiple files. Creating the connection multiple times may be inefficient and not necessary. Therefore, it's better to create a singleton instance to be reused across files.

Below is a basic example that only passes the hostname option.

helpers/redis.ts

  import { redisConnect } from '../deps.ts';
  
  const redisClient = await redisConnect({
   hostname: '127.0.0.1',
  });
  console.log(await redisClient.ping());
  
  export { redisClient };

Below is another example that passes the optional options.

helpers/redis.ts

  import { redisConnect } from '../deps.ts';
  
  const redisClient = await redisConnect({
   hostname: '127.0.0.1',
   port: 6379,
   tls: false,
   db: 1,
   password: '123',
   name: 'woolha-app',
   maxRetryCount: 10,
   retryInterval: 100000,
  });
  console.log(await redisClient.ping());
  
  export { redisClient };

For the below examples, I assume the redis client defined in helpers/redis.ts has been imported.

  import { redisClient } from './helpers/redis.ts';

Set Values

One of the most common operations is set which is used to update the value of a key in redis server.

Set String Value

The below set command is used to set a key to hold the given value.

  set(
    key: string,
    value: string,
    opts?: { ex?: number; px?: number; keepttl?: boolean; mode?: "NX" | "XX" },
  )

Below is a basic usage example for set.

  await redisClient.set('domain', 'woolha.com');

The above code doesn't set the expiry time of the key. You can pass ex option to specify the expiry time in seconds.

  await redisClient.set('domain', 'woolha.com', { ex: 30 * 60 });

If you want to pass the value in milliseconds, you can pass px option instead.

  await redisClient.set('domain', 'woolha.com', { px: 30 * 60 * 1000 });

If you want to update the value of a key without changing the TTL, you can pass keepttl option with the value sets to true. This option only works for redis v6.0 or above.

  await redisClient.set('domain', 'woolha.com', { keepttl: true });

By default, SET command replaces the value if the key already exists or creates a new key otherwise. To change that behavior, you can pass mode option with the value set to NX to only set the value if the key doesn't exist.

  await redisClient.set('domain', 'woolha.com', { mode: 'NX' });

There is another mode XX which only sets the value if the key already exists.

  await redisClient.set('domain', 'woolha.com', { mode: 'XX' });

Set Multiple Values

To set multiple values at once, you can use mset.

  mset(...params: any[])

Example:

  await redisClient.mset({ key1: 'chibi', key2: 'twice' });

Set Hash Value

If you want a key to hold a hash value, you can use hset.

  hset(key: string, ...params: any[])

Example:

  await redisClient.hset('ranks', 'first', 'chibi');
  await redisClient.hset('ranks', 'second', 'twice');

Set List Value

To push an element to a key whose value type is a list, you can use lpush. It will create a new key if the specified key doesn't exist.

  lpush(key: string, ...elements: (string | number)[])

Example:

  await redisClient.lpush('items', '001');
  await redisClient.lpush('items', '002');

To replace an element at a certain index, you can use lset. Make sure the index is not out of range.

  lset(key: string, index: number, element: string | number)

Example:

  await redisClient.lset('items', 1, '003');

Get Values

Below are the examples of how to get stored values.

Get String Value

To get the value of a key whose value is a string, you can use get function.

  get(key: string)

Example:

  const value = await redisClient.get('domain');
  console.log(`value: ${value}`);

If the key doesn't exist, it will return undefined.

To get multiple values, you can use mget function. The return value is a list of values for each key.

Get Multiple Values

   mget(...keys: string[])

Example:

  const values = await redisClient.mget('key1', 'key2');

It will return an undefined element for a key that doesn't exist.

Get Hash Value

To get the value of a key that holds a hash value, you can use hget.

  hget(key: string, field: string)

Example:

  const value = await redisClient.hget('ranks', 'first');

Get List Value

To get the value of a key that holds a list value, you can use lrange.

  lrange(key: string, start: number, stop: number)

Example:

  const values = await redisClient.lrange('items', 0, -1);
  console.log(`values: ${values}`);

Delete Values

Delete Key

If a key is no longer used, you may want to delete it. To delete a key, use del function and pass the key(s) as the argument(s).

  del(...keys: string[])

Example:

  await redisClient.del('key1');

It can also be used to delete multiple keys at once.

  await redisClient.del('key1', 'key2');

Delete List Elements

To remove and return the first element of a list, you can use lpop.

  lpop(key: string)

Example:

  const value = await redisClient.lpop('items');
  console.log(`value: ${value}`);

To remove n elements with certain values, you can use lrem.

  lrem(key: string, count: number, element: string | number)

Example:

  const removeCount = await redisClient.lrem('items', 2, '001');
  console.log(`values: ${removeCount}`);

Using Raw Commands

If the provided functions don't meet your requirement, you can execute raw commands instead. The output is an array whose values depend on the command type.

  console.log(await redisClient.executor.exec('SET', 'name', 'woolha', 'EX', 60)); // [ "status", "OK" ]
  console.log(await redisClient.executor.exec('GET', 'name')); // [ "bulk", "woolha" ]

Output:

  [ "status", "OK" ]
  [ "bulk", "woolha" ]

Summary

That's how to use redis in a Deno application. The third-party redis module can be used to simplify the process. It already has many functions for different commands other than those in this tutorial which can be read on the source code.