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.