{"id":246,"date":"2022-12-14T20:38:38","date_gmt":"2022-12-14T19:38:38","guid":{"rendered":"https:\/\/chigisoft.com\/blog\/?p=246"},"modified":"2023-07-15T14:31:38","modified_gmt":"2023-07-15T13:31:38","slug":"redis-cloud-developers-experience-with-typescript-part-2","status":"publish","type":"post","link":"https:\/\/chigisoft.com\/blog\/redis-cloud-developers-experience-with-typescript-part-2\/","title":{"rendered":"REDIS Cloud Developers&#8217; Experience With TypeScript &#8211; Part 2"},"content":{"rendered":"\n<p>Welcome to the second part of this tutorial<\/p>\n\n\n\n<p>If you are just joining us I will recommend you check out the first edition: <a href=\"https:\/\/chigisoft.com\/blog\/redis-cloud-developers-experience-with-typescript-part-1\/\">REDIS Cloud Developers&#8217; Experience With TypeScript &#8211; Part 1<\/a>.<\/p>\n\n\n\n<p>In this blog, we are going to learn how to set up a Redis Cloud account but before we do that let&#8217;s talk about the benefits of using <strong><a href=\"https:\/\/redis.com\/redis-enterprise-cloud\/overview\/\" target=\"_blank\" rel=\"noopener\">Redis Enterprise<\/a><\/strong> or <strong><a href=\"https:\/\/redis.com\/redis-enterprise-cloud\/overview\/\" target=\"_blank\" rel=\"noopener\">Redis Enterprise Cloud<\/a><\/strong> on our application.<\/p>\n\n\n\n<p>In the previous article, we were storing data on our local storage and I mentioned such a method is only applicable or recommended for personal test development. If you are developing an application that will be used on production then you have to get a bigger memory by purchasing and setting up your own server and ensuring your server is up and running whenever it is needed. We all know that setting up a personal server or servers is tedious and doesn&#8217;t come cheap. This is where Cloud Service Providers come to play.<\/p>\n\n\n\n<h5 id=\"redis-enterprise\" class=\"wp-block-heading\">Redis Enterprise<\/h5>\n\n\n\n<p>Redis Enterprise is a multi-tenancy Cloud Service Provider that allows you to deploy and self-manage your data by yourself. Instead of spending so much to acquire and set up your own server you can create a free account on the Redis Cloud and deploy your dataset for a far cheaper cost. Some of the benefits of using Redis Enterprise: Cost efficiency, High Availability, Sharding, Security, Support, Automation and Backup. Imagine doing all these on your own or setting up a team to manage it. That will be pretty expensive!<\/p>\n\n\n\n<h5 id=\"redis-account-set-up\" class=\"wp-block-heading\">Redis Account Set Up<\/h5>\n\n\n\n<p>Use this <strong><a href=\"https:\/\/redis.com\/try-free\/\" target=\"_blank\" rel=\"noopener\">link<\/a><\/strong> to create a free account or you can <strong><a href=\"https:\/\/app.redislabs.com\/#\/login\" target=\"_blank\" rel=\"noopener\">login<\/a><\/strong> into your account if you already have one. For those of us who are new on Redis then follow the instructions to set up your account.<\/p>\n\n\n\n<p>Go to the account page and create an account by filling out the form and clicking on <code>Get Started<\/code> or sign up with your GitHub or Google Account button.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/drive.google.com\/uc?export=view&amp;id=1eEIQiECQQ1aqvWpAwXo0OJE57--qDYph\" alt=\"\"\/><\/figure>\n\n\n\n<p>If you are new to Redis Enterprise or Redis Cloud there is a free $200 coupon you can use.<\/p>\n\n\n\n<p>After creating the account you should have an interface similar to the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/drive.google.com\/uc?export=view&amp;id=1uUNoBLexqVn0kJe793rajYxsa291gZ32\" alt=\"\"\/><\/figure>\n\n\n\n<p>Click on the <code>New subscription<\/code> button. it will direct you to the List of Plan page.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/drive.google.com\/uc?export=view&amp;id=11AOWgPPkMeDLy2n1smTX-UdT-fbK_b9J\" alt=\"\"\/><\/figure>\n\n\n\n<p>Redis has a free plan that comes with 30MB of storage space. I recommend this free plan for test purposes. Go ahead and select your plan. For this tutorial, I am using the free plan. Scroll down to the end of the page, enter a subscription name and click on the <code>Create subscription<\/code> button.<\/p>\n\n\n\n<p>You can use the Flexible or Annual plan and pay with your free $200 coupon. The code is TIGER200.<\/p>\n\n\n\n<p>The Redis cloud server is up and running.<\/p>\n\n\n\n<p>Let&#8217;s create the database that will hold our records. Click on the <code>New database<\/code> to create a database:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/drive.google.com\/uc?export=view&amp;id=1ZHddQvYvz7VUEIPaERvIkqgzJWhHv0k9\" alt=\"\"\/><\/figure>\n\n\n\n<p>Enter a database name, select the <code>Redis Stack<\/code> under Type, scroll down and click on the <code>Activate database<\/code> button on the top-right of the page.<\/p>\n\n\n\n<p>Before we proceed further let me introduce you to <strong>Redis Stack<\/strong>.<\/p>\n\n\n\n<h5 id=\"redis-stack\" class=\"wp-block-heading\">Redis Stack<\/h5>\n\n\n\n<p>Redis Stack is a bundle of Redis modules that are embedded in Redis that enables developers to easily build real-time applications by enabling you to define your data through data modelling. Mind you Redis Stack does not replace Redis Open Source instead is an enhancement to migrate from using Redis just for caching to creating data models and still maintaining performance and reliability. Redis modules are made up of RedisJSON, RediSearch, RedisGraph, RedisTimeSeries and RedisBloom. You can find more details on Redis Stack <a href=\"https:\/\/redis.io\/docs\/stack\/\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n\n\n\n<p>Now we have a database that is ready to be used.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/drive.google.com\/uc?export=view&amp;id=1niQiAd03CYH2s_d-ILULZ4wEE8_YxkxZ\" alt=\"\"\/><\/figure>\n\n\n\n<p>With our database set-up completed, let&#8217;s go to our application and reconfigure the database connection. Adding your remote credentials to your application can be a little bit tricky so I need you to pay attention to these instructions. A sample of how your remote URL should look like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">redis:\/\/username:password@public-endpoint<\/pre>\n\n\n\n<p>Go to your <code>.env<\/code> file add a new variable with the sample URL:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">REMOTE_REMOTE_URL=redis:\/\/username:password@public-endpoint<\/pre>\n\n\n\n<p>On your cloud database page scroll down to the <code>Security<\/code> section under <code>Configuration<\/code> tab, copy your username and password.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/drive.google.com\/uc?export=view&amp;id=1gCJTAVmuI-OtnZSlpOCxobw18x4pbmCP\" alt=\"\"\/><\/figure>\n\n\n\n<p>Where you have the username on the local URL replace it with your Redis remote database username and replace the local password with the remote password.<\/p>\n\n\n\n<p>Scroll up to the <code>General<\/code> section under the same <code>Configuration<\/code> tab copy the Public end-point value and paste it on your local URL. Your URL on the the <code>.env<\/code> file should look like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># main<br>REDIS_REMOTE_URL=redis:\/\/default:szNKL1W***f94S**ctD5XK**Y4z**o57@redis-17630.***********.cloud.redislabs.com:17630<br>\u200b<br>#sample<br>REMOTE_REMOTE_URL=redis:\/\/username:password@public-endpoint<\/pre>\n\n\n\n<p>Go to your <code>src\/connection.ts<\/code> script, replace the <code>process.env.REDIS_URL<\/code> with <code>process.env.REDIS_REMOTE_URL<\/code>. Restart your application. Your application should run as if nothing happened.<\/p>\n\n\n\n<p>The next step is to open Postman and hit the create endpoint. This time around your record will be stored on the remote database.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/drive.google.com\/uc?export=view&amp;id=1HG169SvgBNYii4kNlSLnJfcjNZxoUcC2\" alt=\"\"\/><\/figure>\n\n\n\n<p>We need to populate our database with more records. Go ahead and add your favourite novels or literature books to your database.<\/p>\n\n\n\n<p>Let&#8217;s fetch all the records that we have stored so far on our database. Go to your <code>src\/controllers\/BookController.ts<\/code> script and add the following methods to the BookController class:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public static getBooks = async (\nreq: Request, \nres: Response, \nnext: NextFunction\n) =&gt; {\n &nbsp; &nbsp; &nbsp; &nbsp;try {\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const result = await (await BookRepo()).search().return.all()\n\u200b\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return res.send({\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status: 'success',\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data: result\n &nbsp; &nbsp; &nbsp;  })\n\u200b\n &nbsp; &nbsp; &nbsp;  } catch (error) {\n &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next(error)\n &nbsp; &nbsp; &nbsp;  }\n &nbsp;  }<\/pre>\n\n\n\n<p>If you skipped or missed the first part of this tutorial I recommend you use the link at the top of this blog to get yourself updated<\/p>\n\n\n\n<p>Navigate to your <code>routes.ts<\/code> file and add the following endpoint:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">router.get('\/books', BookController.getBooks)<\/pre>\n\n\n\n<p>Your endpoint should fetch an array of all the books stored in your database. Go to your Postman and hit the endpoint:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/drive.google.com\/uc?export=view&amp;id=1GAkEQYPsu0IWt4sXjjbKZnXNcUiMqNh0\" alt=\"\"\/><\/figure>\n\n\n\n<p>Now we have a list of all our records.<\/p>\n\n\n\n<p>Let&#8217;s add other functionalities to our application.<\/p>\n\n\n\n<p>Let&#8217;s assume we have readers on the platform. We want to know about books that are often read by users on our platform. At this point, we want to make use of some commands from core Redis (i.e. Redis open source). We have to install the Redis client that supports NodeJs which will enable our application to utilise the Redis command. I will be using the <code>node-redis<\/code> npm package but you are free to check out other clients <strong><a href=\"https:\/\/redis.io\/resources\/clients\/#nodejs\" target=\"_blank\" rel=\"noopener\">here<\/a><\/strong>. Open your terminal and install the package:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">yarn add redis<\/pre>\n\n\n\n<p>We have to refactor the Redis connection again. Go to your <code>src\/connection.ts<\/code> script:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">import 'dotenv\/config'<br>import { Client } from 'redis-om'<br>import { createClient } from 'redis'<br>\u200b<br>const url = process.env.REDIS_REMOTE_URL<br>\u200b<br>export async function redisConnection() {<br> &nbsp; &nbsp;const connection = createClient({ url })<br> &nbsp; &nbsp;await connection.connect()<br>\u200b<br> &nbsp; &nbsp;return connection<br>}<br>\u200b<br>export async function redisOmConnection() {<br> &nbsp; &nbsp;const client = new Client()<br> &nbsp; &nbsp;const redisConn = await client.use(await redisConnection())<br>\u200b<br> &nbsp; &nbsp;\/\/ to check for connection. you can delete it after we have confirmed our connection is successful<br> &nbsp; &nbsp;const dbCheck = await client.execute(['PING']);<br> &nbsp; &nbsp;console.log(dbCheck)<br> &nbsp; &nbsp;<br> &nbsp; &nbsp;return redisConn<br>}<\/pre>\n\n\n\n<p>Go to your <code>src\/app.ts<\/code> and replace the <code>redisClient<\/code> method with the new one:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">import express from 'express';<br>import { redisOmConnection } &nbsp;from '.\/connection';<br>import router from '.\/routes';<br>\u200b<br>const app = express()<br>app.use(express.json());<br>\u200b<br>const PORT = process.env.PORT || 3000<br>\u200b<br>app.use('\/api\/v1', router);<br>\u200b<br>app.listen(PORT, async () =&gt; {<br> &nbsp; &nbsp;await redisOmConnection();<br> &nbsp; &nbsp;console.log(`app is running on port ${PORT}`)<br>})<\/pre>\n\n\n\n<p>Restart your application.<\/p>\n\n\n\n<p>We want to know popular books by how often users read the book. Every time a user selects and start reading a book, this endpoint is called. On the <code>src\/routes.ts<\/code> add this endpoint:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">router.post('\/read\/:id', BookController.bookRead)<\/pre>\n\n\n\n<p>Add this method to the BookController class <code>src\/controllers\/BookController.ts<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> &nbsp; &nbsp;public static bookRead = async (req: Request, res: Response, next: NextFunction) =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;const key = req.params.id<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;try {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ check if key exist<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;const keyExist = await (await redisConnection()).EXISTS(key)<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;let result;<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (keyExist == 0) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;await (await redisConnection()).SET(key, '0')<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;result = await (await redisConnection()).INCR(key)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  } else {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ returns 'ok' if command was executed successully<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;result = await (await redisConnection()).INCR(key)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  }<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return res.send({<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status: 'success',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data: result<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  })<br> &nbsp; &nbsp; &nbsp;  } catch (error) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next(error)<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp;  }<\/pre>\n\n\n\n<p>Try hitting the endpoint with a different book Id.<\/p>\n\n\n\n<p>Create an endpoint that will return the number of times a book has been read. Add this method to the BookController class:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> &nbsp; &nbsp;public static popularBookByReading = async (req: Request, res: Response, next: NextFunction) =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;const keyArr = req.body.keys<br> &nbsp; &nbsp; &nbsp; &nbsp;console.log(keyArr)<br> &nbsp; &nbsp; &nbsp; &nbsp;try {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;const result = await (await redisConnection()).MGET([keyArr[0], keyArr[1], keyArr[2], keyArr[3]])<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return res.send({<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status: 'success',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data: result<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  })<br> &nbsp; &nbsp; &nbsp;  } catch (error) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next(error)<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp;  }<\/pre>\n\n\n\n<p>In your route file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">router.post('\/books\/poupular', BookController.popularBookByReading)<\/pre>\n\n\n\n<p>On your Postman create an array and paste copies of your book Ids inside the array:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/drive.google.com\/uc?export=view&amp;id=17VeA2WhnURhBQFHLukYpIQY-HbwBSoPh\" alt=\"\"\/><\/figure>\n\n\n\n<p>An overview of the scripts in the application.<\/p>\n\n\n\n<p><code>src\/repositories\/BookRepo.ts<\/code><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">import { Entity, Schema } from 'redis-om';<br>import { redisOmConnection } &nbsp;from '..\/connection'<br>\u200b<br>class Book extends Entity {}<br>\u200b<br>const BookSchema: any = new Schema(Book, {<br> &nbsp; &nbsp;title: { type: 'string' },<br> &nbsp; &nbsp;author: { type: 'string' },<br> &nbsp; &nbsp;pages: { type: 'number' },<br> &nbsp; &nbsp;publisher: { type: 'string' },<br> &nbsp; &nbsp;category: { type: 'string' },<br> &nbsp; &nbsp;publishedDate: { type: 'date' },<br>},{<br> &nbsp; &nbsp;dataStructure: 'JSON'<br>});<br>\u200b<br>\u200b<br>const setup = async () =&gt; {<br> &nbsp; &nbsp;const bookRepo = (await redisOmConnection()).fetchRepository(BookSchema)<br> &nbsp; &nbsp;await bookRepo.createIndex()<br> &nbsp; &nbsp;return bookRepo;<br>\u200b<br>}<br>\u200b<br>export default setup<\/pre>\n\n\n\n<p><code>src\/controllers\/BookController.ts<\/code><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">import { Request, Response, NextFunction } from 'express'<br>import BookRepo from '..\/repositories\/BookRepo'<br>import { redisConnection } from '..\/connection'<br>\u200b<br>export default class BookController {<br> &nbsp; &nbsp;public static createBook = async (req: Request, res: Response, next: NextFunction) =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;try {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;const result = await (await BookRepo()).createAndSave(req.body)<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return res.send({<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status: 'success',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data: result<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  })<br> &nbsp; &nbsp; &nbsp;  } catch (error) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next(error)<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;public static getBookById = async (req: Request, res: Response, next: NextFunction) =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;try {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;const result = await (await BookRepo()).fetch(req.params.id)<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return res.send({<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status: 'success',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data: result,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  })<br> &nbsp; &nbsp; &nbsp;  } catch (error) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next(error)<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;public static getBooks = async (req: Request, res: Response, next: NextFunction) =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;try {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const result = await (await BookRepo()).search().return.all()<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return res.send({<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status: 'success',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data: result,<br> &nbsp; &nbsp; &nbsp;  })<br>\u200b<br> &nbsp; &nbsp; &nbsp;  } catch (error) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next(error)<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;public static bookRead = async (req: Request, res: Response, next: NextFunction) =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;const key = req.params.id<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;try {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ check if key exist<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;const keyExist = await (await redisConnection()).EXISTS(key)<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;let result;<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (keyExist == 0) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;await (await redisConnection()).SET(key, '0')<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;result = await (await redisConnection()).INCR(key)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  } else {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ returns 'ok' if command was executed successully<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;result = await (await redisConnection()).INCR(key)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  }<br>\u200b<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return res.send({<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status: 'success',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data: result<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  })<br> &nbsp; &nbsp; &nbsp;  } catch (error) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next(error)<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;public static popularBookByReading = async (req: Request, res: Response, next: NextFunction) =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;const keyArr = req.body.keys<br> &nbsp; &nbsp; &nbsp; &nbsp;console.log(keyArr)<br> &nbsp; &nbsp; &nbsp; &nbsp;try {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;const result = await (await redisConnection()).MGET([keyArr[0], keyArr[1], keyArr[2], keyArr[3]])<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return res.send({<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status: 'success',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data: result<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  })<br> &nbsp; &nbsp; &nbsp;  } catch (error) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next(error)<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp;  }<br>}<\/pre>\n\n\n\n<p><code>src\/routes.ts<\/code><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">import express, { Router } from 'express';<br>import BookController from '.\/controllers\/BookController';<br>\u200b<br>const router = express.Router();<br>\u200b<br>router.post('\/books', BookController.createBook)<br>router.get('\/books\/:id', BookController.getBookById)<br>router.get('\/books', BookController.getBooks)<br>router.post('\/read\/:id', BookController.bookRead)<br>router.post('\/books\/popular', BookController.popularBookByReading)<br>\u200b<br>export default router<\/pre>\n\n\n\n<h5 id=\"conclusion\" class=\"wp-block-heading\">Conclusion<\/h5>\n\n\n\n<p>We have come to the end of this series.<\/p>\n\n\n\n<p>I hope you learnt a lot from this article. You can go ahead and create more functionalities such as user registration and login.<\/p>\n\n\n\n<p>As usual, I am in the comment section waiting for your feedback.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/learn.chigisoft.com\/product-design\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"414\" src=\"https:\/\/chigisoft.com\/blog\/wp-content\/uploads\/2023\/07\/Product-Bootcamp-Registration-2023-2-1024x414.png\" alt=\"\" class=\"wp-image-509\" srcset=\"https:\/\/chigisoft.com\/blog\/wp-content\/uploads\/2023\/07\/Product-Bootcamp-Registration-2023-2-1024x414.png 1024w, https:\/\/chigisoft.com\/blog\/wp-content\/uploads\/2023\/07\/Product-Bootcamp-Registration-2023-2-300x121.png 300w, https:\/\/chigisoft.com\/blog\/wp-content\/uploads\/2023\/07\/Product-Bootcamp-Registration-2023-2-768x310.png 768w, https:\/\/chigisoft.com\/blog\/wp-content\/uploads\/2023\/07\/Product-Bootcamp-Registration-2023-2-390x158.png 390w, https:\/\/chigisoft.com\/blog\/wp-content\/uploads\/2023\/07\/Product-Bootcamp-Registration-2023-2-820x331.png 820w, https:\/\/chigisoft.com\/blog\/wp-content\/uploads\/2023\/07\/Product-Bootcamp-Registration-2023-2-1180x477.png 1180w, https:\/\/chigisoft.com\/blog\/wp-content\/uploads\/2023\/07\/Product-Bootcamp-Registration-2023-2.png 1332w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p><em><strong>This post is in collaboration with <a href=\"https:\/\/redis.io\/\" target=\"_blank\" rel=\"noopener\">Redis<\/a><\/strong><\/em><\/p>\n\n\n\n<h5 id=\"related\" class=\"wp-block-heading\">Related<\/h5>\n\n\n\n<p><strong><a href=\"https:\/\/redis.com\/try-free\/?utm_campaign=write_for_redis\" target=\"_blank\" rel=\"noopener\">Try Redis Cloud for free<\/a><\/strong><\/p>\n\n\n\n<p><strong><a href=\"https:\/\/redis.info\/3LC4GqB\" target=\"_blank\" rel=\"noopener\">Redis Developer Hub &#8211; tools, guides, and tutorials about Redis<\/a><\/strong><\/p>\n\n\n\n<p><strong><a href=\"https:\/\/redis.info\/3wMR7PR\" target=\"_blank\" rel=\"noopener\">RedisInsight Desktop GUI<\/a><\/strong><\/p>\n\n\n\n<p><strong><a href=\"https:\/\/redis.info\/3Ga9YII\" target=\"_blank\" rel=\"noopener\">Watch this video on the benefits of Redis Cloud over other Redis providers<\/a><\/strong><\/p>\n\n\n\n<h5 id=\"also-related\" class=\"wp-block-heading\">Also related:<\/h5>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-chigisoft-blog wp-block-embed-chigisoft-blog\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"LxYh7pmzRB\"><a href=\"https:\/\/chigisoft.com\/blog\/redis-cloud-developers-experience-with-typescript-part-1\/\">REDIS Cloud Developers&#8217; Experience With TypeScript &#8211; Part 1<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"&#8220;REDIS Cloud Developers&#8217; Experience With TypeScript &#8211; Part 1&#8221; &#8212; Chigisoft Blog\" src=\"https:\/\/chigisoft.com\/blog\/redis-cloud-developers-experience-with-typescript-part-1\/embed\/#?secret=HsKtuZampR#?secret=LxYh7pmzRB\" data-secret=\"LxYh7pmzRB\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-chigisoft-blog wp-block-embed-chigisoft-blog\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"rNSErKM2O5\"><a href=\"https:\/\/chigisoft.com\/blog\/redis-om-developer-experience-using-node-js\/\">Redis OM: Developer Experience using Node.Js<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"&#8220;Redis OM: Developer Experience using Node.Js&#8221; &#8212; Chigisoft Blog\" src=\"https:\/\/chigisoft.com\/blog\/redis-om-developer-experience-using-node-js\/embed\/#?secret=dXSPaWVgSX#?secret=rNSErKM2O5\" data-secret=\"rNSErKM2O5\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"Welcome to the second part of this tutorial If you are just joining us I will recommend you check out the first edition: REDIS Cloud Developers&#8217; Experience With TypeScript &#8211;&hellip;\n","protected":false},"author":3,"featured_media":101,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,14],"tags":[21,71,15,70,9,69],"class_list":{"0":"post-246","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-tech","8":"category-devops","9":"tag-tutorial-2","10":"tag-javascript","11":"tag-nodejs","12":"tag-nosql","13":"tag-redis","14":"tag-typescript"},"_links":{"self":[{"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/posts\/246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/comments?post=246"}],"version-history":[{"count":4,"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/posts\/246\/revisions"}],"predecessor-version":[{"id":511,"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/posts\/246\/revisions\/511"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/media\/101"}],"wp:attachment":[{"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/media?parent=246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/categories?post=246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/chigisoft.com\/blog\/wp-json\/wp\/v2\/tags?post=246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}