Buscar

Banco de dados em tempo real com NodeJS e mongoDB


Prévia do material em texto

04/10/2019 mongoDB: Banco de dados em tempo real com Node.js - Eduardo Rabelo - Medium
https://medium.com/@oieduardorabelo/mongodb-banco-de-dados-em-tempo-real-com-node-js-318e97efc59f 1/8
mongoDB: Banco de dados em tempo
real com Node.js
Atualizações em tempo real com Change Streams API
Eduardo Rabelo
Oct 18, 2018 · 6 min read
Você já se viu naquele cenário em que você quer atualizar a sua interface o mais rápido
possível após mudanças no seu banco de dados mongo? Por exemplo, um novo usuário
é adicionado e você quer atualizar a interface sem precisar fazer uma chamada para
sua API ou fazer um constante polling. Escutei um sim? Então esse artigo é para você!
Existem ótimas soluções para esse cenário, principalmente banco de dados criados
para atualizações em tempo real, como Firebase e RethinkDB, a verdade é que você
também pode criar a mesma solução usando mongoDB e a implementação é bem
simples! mongoDB tem uma API chamada Change Streams, que permite adicionar
ganchos ao seu banco de dados.
04/10/2019 mongoDB: Banco de dados em tempo real com Node.js - Eduardo Rabelo - Medium
https://medium.com/@oieduardorabelo/mongodb-banco-de-dados-em-tempo-real-com-node-js-318e97efc59f 2/8
O método que vou mostrar utiliza replicaSets, você também criar a mesma solução em
Sharded Clusters (para saber mais sobre ambos, clique nos links disponíveis).
Iniciando mongoDB em modo réplica
Nossa primeira etapa é converter o modo padrão do mongoDB para utilizar um
conjunto de réplicas (replica sets).
Precisamos disso porque Change Streams não está disponível no modo padrão do
mongoDB. Pode soar mais complexo, mas confie em mim, é bem simples!
Tenha certeza de ter parado todas as instâncias do mongoDB na sua máquina e
após isso, vamos rodar:
$ mongod --dbpath=/usr/local/var/mongodb --replSet rs0
O comando acima irá iniciar uma instância do mongo como uma réplica chamada rs0.
O caminho usado em --dbpath é o padrão para macOS quando instalamos mongoDB
com Homebrew. Você pode especificar o caminho desejado, não é necessário utilizar o
mesmo acima.
Agora que nossa instância está rodando em modo réplica, antes de criar um novo banco
de dados, nós precisamos iniciar o nosso conjunto de réplicas. Para fazer isso, abra uma
nova aba no seu terminal e conecte ao mongo shell.
$ mongo
$ rs.initiate()
Agora, vamos criar um banco de dados chamado UserDB :
$ use UserDB
E vamos inserir dois usuários:
04/10/2019 mongoDB: Banco de dados em tempo real com Node.js - Eduardo Rabelo - Medium
https://medium.com/@oieduardorabelo/mongodb-banco-de-dados-em-tempo-real-com-node-js-318e97efc59f 3/8
$ db.users.insertMany([ 
 { name: "Bebeto" },
 { name: "Ana Paulo" }
])
Com isso, criamos um banco de dados chamado UserDB e uma collection chamada
users .
Tudo pronto do lado do nosso banco de dados. Vamos criar uma pequena aplicação
para testar nossa stream API.
Uma aplicação de exemplo
Vamos criar uma aplicação para testar o modo réplica com tempo real do mongoDB:
$ mkdir mongo-replica
$ cd mongo-replica
$ yarn add socket.io mongodb mongoose
$ touch {client,models,server}.js
Modelo User do mongoose
Em models.js vamos adicionar:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
 name: {
 type: String,
 required: [true, "Need User name"]
 }
});
const User = mongoose.model("User", UserSchema);
module.exports = User;
Servidor com Socket.io para conexão em tempo real
Atualize seu server.js para:
04/10/2019 mongoDB: Banco de dados em tempo real com Node.js - Eduardo Rabelo - Medium
https://medium.com/@oieduardorabelo/mongodb-banco-de-dados-em-tempo-real-com-node-js-318e97efc59f 4/8
const http = require("http");
const serverSocketIO = require("socket.io");
const mongoose = require("mongoose");
//
// default env vars
//
const {
 // **[A]**
 MONGODB_URL = "mongodb://localhost:27017/UserDB?replicaSet=rs0",
 SERVER_HOST = "localhost",
 SERVER_PORT = 3000
} = process.env;
//
// mongoose models
//
const User = require("./models");
//
// http server and socket.io socket
//
const server = http.createServer((req, res) => {
 res.end("Hello World!");
});
const serverIO = serverSocketIO(server); // **[B]**
//
// starting server and db conn
//
mongoose.connect(
 MONGODB_URL,
 { useNewUrlParser: true },
 err => {
 if (err) {
 console.log(`[SERVER_ERROR] MongoDB Connection:`, err);
 process.exit(1);
 }
 // **[C]**
 User.watch().on("change", change => {
 console.log(`[SERVER_CHANGE_STREAM] User:`, change);
 serverIO.emit("changeData", change);
 });
 serverIO.on("connection", function() {
 console.log("[SERVER_SOCKET_IO] New Connection:", client.id);
 });
 server.listen(SERVER_PORT, SERVER_HOST, () => {
 console.log(`[SERVER] Running at 
${SERVER_HOST}:${SERVER_PORT}`);
 });
 }
);
04/10/2019 mongoDB: Banco de dados em tempo real com Node.js - Eduardo Rabelo - Medium
https://medium.com/@oieduardorabelo/mongodb-banco-de-dados-em-tempo-real-com-node-js-318e97efc59f 5/8
Tem bastante coisa acontecendo aqui, mas vamos aos pontos imporantes:
[A]: Estamos usando a URL padrão do mongoDB, utilizando a porta 27017, o
banco que criamos anteriormente UserDB e o mais importante nessa URL é que
estamos mencionando a réplica explicitamente.
[B]: Criamos um servidor http e passamos para o socket.io, no final do script,
podemos ver que estamos escutando na porta 3000 e no host localhost , com isso,
podemos testar nossa Stream API utilizando Socket.io
[C]: Estamos utilizando a API .watch() do mongoose que é um pequeno wrapper
em cima da Change Streams API do driver do mongoDB. Adicionamos o evento
.on("change", ... do stream criado no model User. Após qualquer operação na
collection UserDB.users, esse callback será chamado, passando o objeto change
que contém o documento alterado e metadata sobre a collection, operação
realizada, etc.
Dica: Não coloque NENHUMA Change Stream dentro de callbacks do Socket.io, como
io.on("connection", ... etc. O uso de CPU por causa disso irá criar um picos,
chegando a 95% ou mais.
Criando um cliente simples para testar o Socket.io e Change Stream
Para testar tudo isso, vamos adicionar ao nosso client.js o seguinte:
const io = require('socket.io-client');
const socket = io.connect(`http://localhost:3000`); // **[A]**
socket.on("connect", () => {
 console.log(`[CLIENT_SOCKET_IO] Connected:`, socket.connected)
})
socket.on("changeData", payload => { // **[B]**
 console.log(`[CLIENT_CHANGE_STREAM] User:`, payload)
})
[A]: Uma conexão simulando um cliente para nosso servidor com Socket.io
[B]: Relacionado ao item [D] no nosso server.js , quando for emitido o evento
changeDate nós estamos escutando o evento no lado do cliente e podemos reagir
conforme necessário.
04/10/2019 mongoDB: Banco de dados em tempo real com Node.js - Eduardo Rabelo - Medium
https://medium.com/@oieduardorabelo/mongodb-banco-de-dados-em-tempo-real-com-node-js-318e97efc59f 6/8
Testando tudo junto
Você vai precisar de 3 abas no seu terminal:
Uma para o MongoDB, criado na primeira sessão desse artigo “Iniciando
MongoDB em modo réplica”
Uma para rodar o server.js com node server.js
Uma para rodar o client.js com node client.js
Ficando com algo como:
Aba MongoDB:
Aba server.js:
Aba client.js:
04/10/2019 mongoDB: Banco de dados em tempo real com Node.js - Eduardo Rabelo - Medium
https://medium.com/@oieduardorabelo/mongodb-banco-de-dados-em-tempo-real-com-node-js-318e97efc59f 7/8
Agora, faça uma alteração na sua collection em UserDB.users, pode ser através do
mongo shell ou de algum aplicativo como MongoDB Compass ou Robot 3T. No meu
caso, irei abrir outra aba no terminal, conectar no mongo shell e adicionarum novo
documento na minha collection:
$ mongo
$ use UserDB
$ db.users.insert({ name: "André" })
Ao fazer isso, perceba que a aba em server.js e client.js foram atualizadas. Isso foi
o callback do nosso User.watch().on("change", ... que foi acionado e também o
evento serverIO.emit("changeData", ... que enviou um evento para todos os sockets
conectados, no nosso caso, o client.js recebeu o payload em socket.on("changeData",
payload => ... .
Parecido com:
Aba server.js:
Aba client.js:
04/10/2019 mongoDB: Banco de dados em tempo real com Node.js - Eduardo Rabelo - Medium
https://medium.com/@oieduardorabelo/mongodb-banco-de-dados-em-tempo-real-com-node-js-318e97efc59f 8/8
Como resultado, a sua instância do MongoDB está atuando como um banco de dados
em tempo real!!1 🎉 🎉🎉
Finalizando
Só falta iniciar um projeto front-end e despachar suas atualizações em tempo real para
seu usuário. Isso tudo funciona a partir do MongoDB 3.6, agora você criar melhores
experiências para seus usuários sem a necessidade de mudar sua stack ou
infraestrutura.
Já utilizou essa API? Tem alguma dia? Compartilha nos comentários! 👋
. . .
⭐ Créditos
Baseado em Using MongoDB as realtime DB with nodeJS, escrito originalmente
por Sharath Vignesh
Adicionado um exemplo completo e expandido a explicação de alguns tópicos e
partes da implementação
Mongodb Nodejs Web Development JavaScript Programming
About Help Legal

Continue navegando