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