DEV Community

Cover image for How to use Redis as a Database with Node.js and Redis OM
Francisco Mendes
Francisco Mendes

Posted on

How to use Redis as a Database with Node.js and Redis OM

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 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:

mkdir redis-node-crud
cd redis-node-crud
Enter fullscreen mode Exit fullscreen mode

Inside the folder we will create the node environment:

npm init -y
Enter fullscreen mode Exit fullscreen mode

Next, we will install the necessary dependencies:

npm install koa @koa/router koa-body redis-om --save
npm install nodemon standard --save-dev
Enter fullscreen mode Exit fullscreen mode

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

{
  "type": "module",
  "scripts": {
    "dev": "nodemon src/main.js",
    "lint": "standard --fix"
  },
}
Enter fullscreen mode Exit fullscreen mode

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

// @/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')
  }
}
Enter fullscreen mode Exit fullscreen mode

The next step will be to create the entity and schema of our api (to be simpler I put it in the same file as the database configuration):

// @/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' }
})
Enter fullscreen mode Exit fullscreen mode

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:

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

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

const router = new Router()

// ...

export { router }
Enter fullscreen mode Exit fullscreen mode

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

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

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:

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

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:

router.post('/post', async (ctx) => {
  const postRepository = client.fetchRepository(postSchema)
  const post = await postRepository.createAndSave({
    ...ctx.request.body
  })
  ctx.body = post
})
Enter fullscreen mode Exit fullscreen mode

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:

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 }
})
Enter fullscreen mode Exit fullscreen mode

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:


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

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

// @/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)
  })
Enter fullscreen mode Exit fullscreen mode

How to run it

To start the api process, run the following command:

npm run dev
Enter fullscreen mode Exit fullscreen mode

To correct the code formatting, run the following command:

npm run lint
Enter fullscreen mode Exit fullscreen mode

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 the link to the github repository.

Top comments (0)