DataARTIGO

CRUD completo com Redis, MongoDB e Node.js

No seguinte artigo, o autor mostra como criar um CRUD completo com o Redis, MongoDB e o Node.js.

Introdução

Dando continuidade ao meu artigo anterior sobre Redis, hoje irei demonstrar como criar uma API utilizando Node.js, MongoDB e o Redis como cache. Caso tenha interesse em ler o artigo anterior, segue o link:

Para pular a etapa de criação de um novo projeto, eu irei utilizar um que eu desenvolvi em um artigo anterior. Caso tenha interesse em clonar esse projeto, segue o link no GitHub: node-express.

Estrutura do projeto

O projeto está bem simples, eu criei um controller contendo os 5 verbos para um CRUD e um diretório para criação das rotas. Abaixo, você tem uma imagem demonstrando a estrutura desse projeto:

projeto scaffold

Para os próximos passos, será necessário um editor de textos. Eu irei utilizar o VS Code, mas você pode escolher um de sua preferência.

O primeiro passo será baixar as bibliotecas necessárias para o utilizar o Redis e o Mongoose. Para isso, abra um terminal e navegue até o seu projeto. Em seguida, execute o comando abaixo:

npm i body-parser mongoose redis --save

O próximo passo será a criação de um Schema. Para isso, crie um arquivo chamado db.js no seguinte caminho ./src/config/db.js. Agora abra esse arquivo no seu editor de textos e atualize ele com o trecho de código abaixo:

var mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1/db_employees');

var Schema = mongoose.Schema;

var personSchema = new Schema({
    name: String,
    mail: String,
    role: String
});


var Person = mongoose.model('Person', personSchema);
module.exports = Person;

O arquivo acima irá criar uma collection. Nós iremos utilizar ela nos próximos passos desse artigo.

Agora, para deixar o código mais organizado, vamos criar um diretório no nosso projeto para os nossos repositórios. Para isso, crie um novo diretório no seguinte path: ./src/repositories/, e dentro dele um arquivo chamado personRepository.js.

estrutura Node Mongo

Esse repositório será responsável pela conexão com o Schema. Atualize o arquivo personRepository.js com o código abaixo:

'use strict';
var mongoose = require('mongoose')
var Person = require('../config/db');


module.exports = new class PersonRepository {

    getAll() {
        return Person.find();
    }

    getById(id) {
        return Person.findById(id);
    }

    create(person) {
        return Person.create(person);
    }

    update(id, person) {

        const updatedperson = {
            name: person.name,
            mail: person.mail,
            role: person.role,
        }

        return Person.findByIdAndUpdate(id, updatedperson, { new: true });
    }

    delete(id) {
        return Person.findByIdAndRemove(id);
    }

}

Antes de atualizar o controller, vamos adicionar o bodyParser no projeto. Abra o seu arquivo app.js e atualize ele com o código abaixo.

const express = require('express');
const app = express();
const router = express.Router();
const bodyParser = require("body-parser");

//Rotas
const index = require('./routes/index');
const personRoute = require('./routes/personRoute');

app.use(bodyParser.urlencoded({
    extended: true
}));

app.use(bodyParser.json());


app.use('/', index);
app.use('/person', personRoute);

module.exports = app;

Agora atualize o seu arquivo ./src/controllers/personController.js com o código a seguir:

'use strict';

const PersonRepository = require('../repositories/personRepository');

exports.get = (req, res, next) => {
    PersonRepository.getAll()
        .then((person) => {
            res.status(200).send(person);
        }).catch(err => res.status(500).send(err))
};

exports.getById = (req, res, next) => {

    PersonRepository.getById(req.params.id)
        .then((person) => {
            res.status(200).send(person);
        }).catch(err => res.status(500).send(err))
};

exports.post = (req, res, next) => {
    const p = req.body;

    PersonRepository.create(p)
        .then((person) => {
            res.status(200).send(person);
        }).catch(err => res.status(500).send(err))
};

exports.put = (req, res, next) => {
    const p = req.body;

    PersonRepository.update(req.params.id, p)
        .then((person) => {
            res.status(201).send(person);
        }).catch(err => res.status(500).send(err))
};

exports.delete = (req, res, next) => {
    PersonRepository.delete(req.params.id)
        .then((person) => {
            res.status(200).send('delete succeeded!');
        }).catch(err => console.error.bind(console, `Error ${err}`))
};

Navegando rapidamente pelo código acima você tem:

  • 03: chamada para o repositório PersonRepository
  • 05 a 43: implementação dos verbos com a chamada ao nosso PersonRepository

Testando as rotas

Para não precisar instalar o MongoDB no meu computador, eu irei utilizar ele dentro de um contêiner Docker. Caso tenha interesse em utilizar o Mongo com Docker, segue link de um artigo onde eu demonstro esse passo a passo:

Agora, para testar as nossas rotas eu irei utilizar o postman. Caso não conheça ele ainda, o postman nos permite enviar requisições HTTP e obter suas respostas.

POST

A primeira rota que nós precisamos testar é o post, ela que irá cadastrar os nossos registros. Com o postman aberto, preencha ele conforme a imagem abaixo:

POST

GET

Agora altere o verbo para GET e veja o resultado abaixo:

GET

GETById

Buscando uma pessoa pelo seu Id:

Get By ID

PUT

Para validar o PUT, eu irei atualizar o campo role para System Architect.

DELETE

Agora vamos deletar o nosso registo:

Bom, com isso nós conseguimos verificar que todos os nossos verbos estão funcionando corretamente. Para que possamos testar o Redis, será necessário ter alguns registros cadastrados. Para isso, eu irei cadastrar o Zé Maria 10x.

Configurando o Redis

Para não precisar instalar o Redis no meu computador, eu irei utilizar ele da mesma forma que estou utilizando o Mongo, dentro de um contêiner Docker. Caso tenha interesse em saber como criar um contêiner com Redis, segue link de um artigo onde eu demonstro esse passo:

O próximo passo será adicionar o Redis no nosso controller. Para isso, atualize o arquivo personController.js com o trecho de código abaixo:

'use strict';

const PersonRepository = require('../repositories/personRepository');

var redis = require('redis');
var client = redis.createClient();

exports.get = (req, res, next) => {

    client.get('allpersons', function (err, reply) {
        if (reply) {
            console.log('redis');
            res.send(reply)
        } else {
            console.log('db');

            PersonRepository.getAll()
                .then((person) => {
                    client.set('allpersons', JSON.stringify(person));
                    client.expire('allpersons', 20);
                    res.status(200).send(person);
                }).catch(err => res.status(500).send(err))
        }
    });

};

exports.getById = (req, res, next) => {

    PersonRepository.getById(req.params.id)
        .then((person) => {
            res.status(200).send(person);
        }).catch(err => res.status(500).send(err))
};

exports.post = (req, res, next) => {
    const p = req.body;

    PersonRepository.create(p)
        .then((person) => {
            res.status(200).send(person);
        }).catch(err => res.status(500).send(err))
};

exports.put = (req, res, next) => {
    const p = req.body;

    PersonRepository.update(req.params.id, p)
        .then((person) => {
            res.status(201).send(person);
        }).catch(err => res.status(500).send(err))
};

exports.delete = (req, res, next) => {
    PersonRepository.delete(req.params.id)
        .then((person) => {
            res.status(200).send('delete succeeded!');
        }).catch(err => console.error.bind(console, `Error ${err}`))
};

O passo anterior foi bem simples, eu adicionei o Redis na linha 05, e em seguida eu criei um cliente na linha 06, depois eu criei um chave chamada allpersons que deve expirar em 20 segundos. Para verificar se a aplicação está batendo no banco ou no Redis, eu criei dois consoles retornando: Redis quando estiver no cache e um outro db para quando a API requisitar os dados do mongo.

Testando o Cache

Agora. para verificar se o Redis está configurado corretamente, execute o código novamente e note no seu terminal que ele bate uma vez no banco e depois fica no Redis por 20 segundos. Abaixo você tem uma imagem demonstrando esse passo:

redis com node.js e mongodb

Com isso nós finalizamos esse artigo. O meu intuito aqui foi demonstrar uma das formas de melhorar a performance dos nossos sistemas. Caso tenha interesse em baixar o código fonte desenvolvido nesse artigo, segue o link no GitHub:

Espero ter ajudado e até um próximo artigo, pessoal!

Microsoft (MVP), atualmente trabalha como Arquiteto de Software para TV Bandeirantes. Nesses últimos anos, focou nas tecnologias criadas pela Microsoft, mas sempre esteve antenado para as novas tecnologias que estão surgindo no mercado. Em um breve resumo, é uma pessoa apaixonada pelo que faz, tem a sua profissão como hobby.

Ver perfil