How to use Redis as a Database with Node.js and Redis OM
Tags: javascript, node, tutorial, webdev
Published: 2022-08-28 17:43:00

### Introduction

Redis is widely known for caching data that is stored in our database not only for faster responses but also because it takes pressure off the database. Just as it is used to create a system of job queues, etc.

However, its functionality doesn't stop there, Redis offers a good number of modules that can be used and one of them is [RedisJSON](https://redis.io/docs/stack/json/) which offers JSON support in Redis, which enhances its use as our primary database of our application.

And as it should be understood by the title and what was written in this introduction, today we are going to create an api with a simple crud but this time we are going to use Redis as a database.

## Getting started

To start, let's create a new project:

```sh
mkdir redis-node-crud
cd redis-node-crud
```

Inside the folder we will create the node environment:

```sh
npm init -y
```

Next, we will install the necessary dependencies:

```sh
npm install koa @koa/router koa-body redis-om --save
npm install nodemon standard --save-dev
```

Then we'll add the following scripts to `package.json`:

```js
{
  "type": "module",
  "scripts": {
    "dev": "nodemon src/main.js",
    "lint": "standard --fix"
  },
}
```

With the project setup completed, we can configure the connection to a Redis instance:

```js
// @/src/db.js
import { Client } from 'redis-om'

export const client = new Client()

export const createClient = async () => {
  if (!client.isOpen()) {
    await client.open('redis://localhost:6379')
  }
}
```

The next step will be to create the [entity](https://github.com/redis/redis-om-node/blob/main/docs/classes/Entity.md) and [schema](https://github.com/redis/redis-om-node/blob/main/docs/classes/Schema.md) of our api (to be simpler I put it in the same file as the database configuration):

```js
// @/src/db.js
import { Client, Entity, Schema } from 'redis-om'

export const client = new Client()

export const createClient = async () => {
  if (!client.isOpen()) {
    await client.open('redis://localhost:6379')
  }
}

class Post extends Entity {}

export const postSchema = new Schema(Post, {
  title: { type: 'string' },
  content: { type: 'string' },
  isPublished: { type: 'boolean' }
})
```

With the configuration of the connection to Redis finished and with our schema defined we can now start working on the api router where we are going to do the CRUD. And with that, we can now import the necessary dependencies and modules:

```js
// @/src/routes.js
import Router from '@koa/router'

import { client, postSchema } from './db.js'

const router = new Router()

// ...

export { router }
```

The first route that we are going to create will return all the data that we have stored in the database:


```js
router.get('/posts', async (ctx) => {
  const postRepository = client.fetchRepository(postSchema)
  await postRepository.createIndex()
  const allPosts = await postRepository.search().returnAll()
  ctx.body = allPosts
})
```

And as we don't always want to get all posts, let's create a route that returns only one post according to the `id` parameter that is provided in the request parameters:

```js
router.get('/posts/:id', async (ctx) => {
  const postRepository = client.fetchRepository(postSchema)
  const post = await postRepository.fetch(ctx.params.id)
  ctx.body = post
})
```

In addition to returning data, we also need to insert some, for that we will create a route where we can add the properties that we specify in our schema:

```js
router.post('/post', async (ctx) => {
  const postRepository = client.fetchRepository(postSchema)
  const post = await postRepository.createAndSave({
    ...ctx.request.body
  })
  ctx.body = post
})
```

If we need to update one of the properties of a specific post, we will create a route where we will send the `id` of the post in the parameters as well as send the properties that we want to update in the body of the request:

```js
router.put('/post/:id', async (ctx) => {
  const postRepository = client.fetchRepository(postSchema)
  const post = await postRepository.fetch(ctx.params.id)

  Object.entries(ctx.request.body).forEach(([key, val]) => {
    post[key] = val
  })

  const postId = await postRepository.save(post)
  ctx.body = { postId, post }
})
```

Last but not least, we need to delete data from the database, for that we are going to create a route that will accept the `id` parameter in the request parameters to delete only a specific post:

```js

router.delete('/post/:id', async (ctx) => {
  const postId = ctx.params.id
  const postRepository = client.fetchRepository(postSchema)
  await postRepository.remove(postId)
  ctx.body = { postId }
})
```

With CRUD finished, we can now create the api entry file, where we will setup the routes and establish the connection with the database.

```js
// @/src/main.js
import Koa from 'koa'
import koaBody from 'koa-body'

import { router } from './routes.js'
import { createClient, client } from './db.js'

const startServer = async () => {
  const app = new Koa()
  await createClient()

  app.use(koaBody())
  app.use(router.routes())

  return app
}

startServer()
  .then(async (app) => {
    await new Promise(resolve => app.listen({ port: 3333 }, resolve))
  })
  .catch(async (err) => {
    console.error(err)
    await client.close()
    process.exit(1)
  })
```

## How to run it

To start the api process, run the following command:

```sh
npm run dev
```

To correct the code formatting, run the following command:

```sh
npm run lint
```

## Conclusion

As usual, I hope you enjoyed the article and that it helped you with an existing project or simply wanted to try it out.

If you found a mistake in the article, please let me know in the comments so I can correct it. Before finishing, if you want to access the source code of this article, I leave [here](https://github.com/FranciscoMendes10866/koa-redis-om) the link to the github repository.