Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Learn why MongoDB was selected as a leader in the 2024 Gartner® Magic Quadrant™
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
MongoDBchevron-right

Como migrar seu aplicativo Node.js do SQL para o MongoDB

Emmanuel John16 min read • Published Jul 09, 2024 • Updated Jul 09, 2024
Node.jsJavaScriptMongoDB
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Com a rápida aprovação da metodologia Agile no desenvolvimento de software, os desenvolvedores agora procuram migrar de bancos de dados SQL para NoSQL para obter mais flexibilidade e dimensionamento horizontal, o que é mais barato e eficiente para o desenvolvimento de software.
A migração de um banco de dados SQL para um banco de dados NoSQL pode ser um desafio devido a fatores importantes, como diferenças no modelo de dados, linguagem de consulta, padrões de acesso e otimização de consultas.
Neste artigo, exploraremos os principais conceitos do MongoDB, como collections, documentos e BSON, e as diferenças na modelagem de dados entre bancos de dados SQL e NoSQL. Também migraremos de um banco de dados relacional (Postgres) para o MongoDB.

Pré-requisitos

Abaixo estão alguns pré-requisitos que você precisará antes de prosseguir com este artigo:
  • Conhecimento de JavaScript
  • Experiência na construção de aplicativos Node.js
  • Experiência com banco de dados SQL e Postgre
  • Node.js ≥v20 instalado

Planejando a migração

Nesta seção, migraremos o banco de dados e as queries de um aplicativo de backend do Node.js do Postgres para o MongoDB. O aplicativo será um aplicativo de lista telefônica pública com os seguintes recursos:
  1. Registro e login do usuário: as senhas são criptografadas usando o bcrypt e o JWT é usado para autenticação.
  2. Operações CRUD:
  • Criar contato: Usuários autenticados podem criar contatos.
  • Obtenha contatos: obtenha contatos com a contagem da taxa de chamadas e detalhes do usuário, filtrados por intervalo de datas e ordenados pela contagem da taxa de chamadas.
  • Obter contato por ID: recupere um único contato por ID para o usuário autenticado.
  • Atualizar contato: usuários autenticados podem atualizar seus contatos.
  • Excluir contato: usuários autenticados podem excluir seus contatos.
Abra psql e execute o seguinte comando para criar as tabelas necessárias para o aplicativo:
1CREATE TABLE users (
2 id SERIAL PRIMARY KEY,
3username VARCHAR(100) UNIQUE NOT NULL,
4 password VARCHAR(100) NOT NULL,
5email VARCHAR(100) UNIQUE NOT NULL,
6created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
7);
8CREATE TABLE contacts (
9 id SERIAL PRIMARY KEY,
10 name VARCHAR(100) NOT NULL,
11phone VARCHAR(20) NOT NULL,
12email VARCHAR(100),
13user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
14created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
15);
16CREATE TABLE rates (
17 id SERIAL PRIMARY KEY,
18 description TEXT NOT NULL,
19contact_id INTEGER REFERENCES contacts(id) ON DELETE CASCADE,
20user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
21created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
22);
Crie um projeto Node.js e instale as seguintes dependências:
1"dependencies": {
2 "bcryptjs": "^2.4.3",
3 "express": "^4.19.2",
4 "jsonwebtoken": "^9.0.2",
5 "pg": "^8.11.5"
6}
Você pode instalar todos os pacotes necessários com o seguinte comando:
1npm install bcryptjs express jsonwebtoken pg
Crie um arquivo.env.postgres e adicione as variáveis de ambiente a seguir. Você precisará alterar os valores para usar as credenciais para se conectar ao seu banco de dados.
1DB_USER=your_username
2DB_HOST=localhost
3DATABASE=your_DB_name
4DB_PASSWORD=your_password
5DB_PORT=5432
6SECRET_KEY=your_jwt_secret_key
Crie um arquivopostgres.jsno diretório raiz do projeto e adicione o seguinte:
1import express from 'express';
2import bcrypt from 'bcryptjs';
3import jwt from 'jsonwebtoken';
4import pg from 'pg';
5
6const { Pool } = pg;
7
8const app = express();
9const port = 3000;
10
11app.use(express.json());
12
13const pool = new Pool({
14 user: process.env.DB_USER,
15 host: process.env.DB_HOST,
16 database: process.env.DATABASE,
17 password: process.env.DB_PASSWORD,
18 port: process.env.DB_PORT,
19});
20
21// JWT secret key
22const SECRET_KEY = process.env.SECRET_KEY;
23
24/* START FEATURE IMPLEMENTATION*/
25
26/* END FEATURE IMPLEMENTATION*/
27
28// Start server
29app.listen(port, () => {
30 console.log(`Server running on port ${port}`);
31});
Certifique-se de que seu package.json inclua "type": "module".
Definimos com sucesso um aplicativo de backend Nodejs e configuramos o banco de dados Postgres usando a estrutura Express.
Você pode iniciar seu servidor executando:
1node --env-file=.env.postgres postgres.js
O uso do parâmetro--env-file injetará as variáveis de ambiente e você poderá usá-las por meio process.env.
Vamos prosseguir com a implementação dos recursos do aplicativo.
Registro do usuário: 
1app.post('/register', async (req, res) => {
2 const { username, email, password } = req.body;
3 const salt = await bcrypt.genSalt(10);
4 const hashedPassword = await bcrypt.hash(password, salt);
5 const result = await pool.query(
6 'INSERT INTO users (username, email, password) VALUES ($1, $2, $3) RETURNING *',
7            [username, email, hashedPassword]
8    );
9    const ...user } = result.rows[0];
10
11    res.status(201).json({...user, password: null});
12});
O endpoint de registro de usuário garante o manuseio seguro de senhas usando bcrypt para o hash da senha e executa uma query SQL para inserir o novo usuário na tabelausers no banco de dados PostgreSQL por meio do pool de conexões.
Login do usuário:
1app.post('/login', async (req, res) => {
2    const { email, password } = req.body;
3
4    const user = await pool.query('SELECT * FROM users WHERE email = $1', [email]);
5
6    let validPass = false;
7
8    if (user.rows[0]) validPass = await bcrypt.compare(password, user.rows[0].password);
9
10    if (!validPass) return res.status(400).json({ message: 'Invalid credentials' });
11
12    const token = jwt.sign({ id: user.rows[0].id, email: user.rows[0].email }, SECRET_KEY, { expiresIn: '1h' });
13
14    res.status(200).json({ token });
15
16});
O endpoint de login do usuário garante o tratamento seguro da autenticação do usuário usando o bcrypt para validação de senha e o JWT para gerenciamento de sessões.
Middleware para autenticar usuários:
1const authenticateToken = (req, res, next) => {
2 const token = req.header('Authorization');
3 if (!token) return res.status(401).json({ message: 'Access Denied' });
4 const verified = jwt.verify(token.split(" ")[1], SECRET_KEY);
5    req.user = verified;
6    next();
7};
Essa função de middleware garante que somente solicitações com tokens JWT válidos possam acessar rotas protegidas, aumentando a segurança do aplicativo.
Criar contato:
1app.post('/contacts', authenticateToken, async (req, res) => {
2 const { name, phone, email } = req.body;
3 const result = await pool.query(
4 'INSERT INTO contacts (name, phone, email, user_id) VALUES ($1, $2, $3, $4) RETURNING *',
5            [name, phone, email, req.user.id]
6        );
7    res.status(201).json(result.rows[0]);
8});
O endpoint create contact cria novos contatos e garante que somente usuários autenticados possam executar essa ação.
Obter contato por ID:
1app.get('/contacts/:id', authenticateToken, async (req, res) => {
2 const { id } = req.params;
3 const result = await pool.query('SELECT * FROM contacts WHERE id = $1 AND user_id = $2', [id, req.user.id]);
4 if (result.rows.length === 0) return res.status(404).json({ message: 'Contact not found' });
5    res.status(200).json(result.rows[0]);
6});
O ponto de extremidade get contact by ID permite que apenas usuários autenticados busquem um contato específico pelo seu ID e verifica se ele pertence ao usuário autenticado.
Contato de atualização:
1app.put('/contacts/:id', authenticateToken, async (req, res) => {
2 const { id } = req.params;
3 const { name, phone, email } = req.body;
4 const result = await pool.query(
5 'UPDATE contacts SET name = $1, phone = $2, email = $3 WHERE id = $4 AND user_id = $5 RETURNING *',
6            [name, phone, email, id, req.user.id]\
7    );
8 if (result.rows.length === 0) return res.status(404).json({ message: 'Contact not found or not authorized' });
9    res.status(200).json(result.rows[0]);
10});
O ponto de extremidade de atualização de contato permite que apenas usuários autenticados acessem e atualizem seus contatos.
Excluir contato:
1app.delete('/contacts/:id', authenticateToken, async (req, res) => {
2 const { id } = req.params;
3 const result = await pool.query('DELETE FROM contacts WHERE id = $1 AND user_id = $2 RETURNING *', [id, req.user.id]);
4 if (result.rows.length === 0) return res.status(404).json({ message: 'Contact not found or not authorized' });
5    res.status(200).json(result.rows[0]);
6});
O ponto de extremidade de exclusão de contato permite que apenas usuários autenticados excluam seus contatos.
Adicionar taxa de chamada:
1app.post('/contacts/:id/rates', authenticateToken, async (req, res) => {
2 const { id } = req.params;
3 const { description } = req.body;
4 const result = await pool.query(
5 'INSERT INTO rates (body, contact_id, user_id) VALUES ($1, $2, $3) RETURNING *',
6    [description, id, req.user.id]
7  );
8  res.status(201).json(result.rows[0]);
9});
O endpoint de adição de taxa de chamada permite que apenas usuários autenticados avaliem um contato específico por sua ID.
As taxas estão associadas a contatos em um relacionamento de um para muitos. A colunacontact_id na tabela de taxas é uma chave estrangeira que faz referência à coluna id na tabela de contatos.
Essa chave estrangeira estabelece um relacionamento em que cada taxa está vinculada a um contato específico.
Ter uma relação definida permite consultas eficientes que podem unir duas ou mais tabelas.
Por exemplo, você pode buscar rapidamente um contato junto com todas as suas taxas associadas ou dados agregados, como o número de taxas por contato.
Obter contatos:
1app.get('/contacts', async (req, res) => {
2 let { startDate, endDate } = req.query;
3 if (!endDate) {
4endDate = new Date().toISOString();
5} else {
6endDate = new Date(endDate).toISOString();
7      }
8
9 if (!startDate) {\
10 const now = new Date();
11 const pastDate = new Date(now);
12pastDate.setDate(now.getDate() - 7);
13        startDate = pastDate.toISOString();
14} else {
15startDate = new Date(startDate).toISOString();
16      }
17
18 const result = await pool.query(`
19            SELECT
20                contacts.id, contacts.name, contacts.phone, contacts.created_at,
21                users.username,
22                COUNT(rates.id) AS call_rate
23            FROM contacts
24            LEFT JOIN users ON contacts.user_id = users.id
25            LEFT JOIN rates ON contacts.id = rates.contact_id
26            WHERE contacts.created_at BETWEEN $1 AND $2
27            GROUP BY contacts.id, users.username
28            ORDER BY call_rate DESC
29        `, [startDate, endDate]);
30  res.status(200).json(result.rows);
31});
O endpoint get contacts recupera e agrega dados de contato, garantindo que somente contatos dentro do intervalo de datas especificado sejam incluídos nos resultados. Ele também fornece informações úteis sobre o número de chamadas associadas a cada contato, ordenadas pelo número de classificações de chamadas.
Cláusula SELECT: a cláusula SELECT seleciona a coluna especificada na tabela para selecionar os dados.
Cláusula FROM: A cláusula FROM especifica a tabela da qual selecionar dados.
LEFT JOIN usuários ON contatos.user_id = users.id: Isso une a tabela de contatos à tabela de usuários com a condição de que o user_id na tabela de contatos corresponda ao id na tabela de usuários.
Taxas de junção à esquerda em contatos.id = taxas.contact_id: Isso une a tabela de contatos à tabela de taxas, com a condição de que o ID na tabela de contatos corresponda ao Contact_id na tabela de taxas.
WHERE contacts.created_at ENTRE $1 E $2: Isso filtra os contatos para incluir apenas aqueles criados entre as datas especificadas por $1 (StartDate) e $2 (EndDate). 
GROUP BY contacts.id, users.username: Isto agrupa os resultados por Contacts.id e users.username. Isso é necessário porque estamos usando uma função agregada (COUNT(rates.id)), e SQL requer que todas as colunas não agregadas na cláusula SELECT sejam incluídas na cláusula GROUP BY.
ORDENAR BY call_rate DESC: Ordena os resultados por call_rate em ordem decrescente (DESC). Isso significa que os contatos com o maior número de taxas (ou chamadas) aparecerão primeiro nos resultados.
Para testar sua implementação, não se esqueça de parar e reiniciar seu servidor.
Como podemos ver, o PostgreSQL segue um modelo de dados relacional. Ao mesmo tempo, o MongoDB é um banco de dados orientado a documentos NoSQL, portanto, precisamos redesenhar nosso esquema para se adequar ao modelo baseado em documentos do MongoDB. Na seção de migração do SQL, identificaremos as entidades e relacionamentos em nosso esquema PostgreSQL e mapeamos para as collections e documentos do MongoDB.

Configurando o MongoDB

Para configurar o MongoDB para uso com nosso aplicativo Node.js, usaremos o MongoDB Atlas, um serviço de banco de dados em várias nuvens que simplifica a implantação e o gerenciamento de seus bancos de dados com apenas alguns cliques.
Ele também oferece uma camada gratuita para sempre, sem requisitos de cartão de crédito. Quão legal é isso? 
Dito isso, acesse o MongoDB Atlas e crie uma conta, caso ainda não tenha uma.

Crie um cluster de banco de dados

Para criar um cluster de banco de dados, siga os Docs. 
Escolha a opção de cluster compartilhado para uma camada gratuita para sempre. A configuração padrão é suficiente para nosso aplicativo de demonstração. 
Ao criar seu cluster de banco de dados, você será solicitado a adicionar um usuário e uma senha de banco de dados para seu cluster de banco de dados. Certifique-se de salvar o nome de usuário e a senha onde você pode referenciar, pois você precisará deles para se conectar ao cluster de banco de dados.

Conectando ao cluster de banco de dados 

Crie um projeto Node.js e instale as seguintes dependências:
1"dependencies": {
2 "express": "^4.19.2",
3 "mongodb": "^8.4.0",
4 "bcryptjs": "^2.4.3",
5 "jsonwebtoken": "^9.0.2",
6}
Você pode instalar as bibliotecas com:
1npm install mongodb express bcryptjs jsonwebtoken
Crie um .env.mongodb arquivo e adicione as seguintes variáveis de ambiente:
1SECRET_KEY=your_jwt_secret_key
2DB_USER=your_cluster_username
3DB_PASSWORD=your_cluster_password
4DATABASE=users
5CLUSTER_URI=your_cluster_uri
Crie um arquivomongodb.jsno diretório raiz do projeto e adicione o seguinte:
1import { MongoClient, ObjectId } from 'mongodb';
2import express from 'express';
3import bcrypt from 'bcryptjs';
4import jwt from 'jsonwebtoken';
5
6const app = express();
7app.use(express.json());
8
9const url = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.CLUSTER_URI}`;
10const client = new MongoClient(url);
11const dbName = process.env.DATABASE;
12const SECRET_KEY = process.env.SECRET_KEY;
13
14await client.connect();
15const db = client.db(dbName);
16const usersCollection = db.collection('users');
17const contactsCollection = db.collection('contacts');
18
19/* START FEATURE IMPLEMENTATION*/
20
21/* END FEATURE IMPLEMENTATION*/
22app.listen(3000, () => {
23 console.log('Server is running on port 3000');
24});
Para usar o await de nível superior, você precisará habilitar o suporte ao módulo ES e garantir que seu package.json tenha "type": "module".
O código acima permite que seu aplicativo Node se conecte ao cluster de banco de dados.
Execute o seguinte comando para iniciar seu servidor Node:
1node --env-file=.env.mongodb mongodb.js

Migrando as queries SQL

Existem duas etapas aqui:
  • Traduza as queries SQL para a API de query do MongoDB.
  • Use o Conversor de query do MongoDB para migrar suas queries SQL para a MongoDB Query API.

Traduzir as consultas SQL para a API MongoDB Query

O driver MongoDB Node.js é um pacote que permite que você se conecte ao MongoDB, execute operações de banco de dados e gerencie collections e documentos. Ele fornece uma solução direta e sem esquema para modelar os dados do aplicativo de forma flexível.
A primeira coisa a considerar para a migração do banco de dados são os modelos de dados. Lembre-se de como criamos tabelas e relacionamentos para o banco de dados Postgres executando o seguinte SQL no terminalpsql :
1CREATE TABLE users (
2 id SERIAL PRIMARY KEY,
3username VARCHAR(100) UNIQUE NOT NULL,
4 password VARCHAR(100) NOT NULL,
5email VARCHAR(100) UNIQUE NOT NULL,
6created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
7);
Aqui está a parte boa: usando o driver MongoDB Node.js, você não precisa definir esquemas. Quando você insere um documento em uma collection, ele é criado com os campos fornecidos com ométodo de inserção.
Registrar:
1app.post('/register', async (req, res) => {
2 const { username, email, password } = req.body;
3
4    const salt = await bcrypt.genSalt(10);
5 const hashedPassword = await bcrypt.hash(password, salt);
6 const user = { username, email, password: hashedPassword };
7 const result = await usersCollection.insertOne(user);
8    res.status(201).json({...user, password: null});
9  });
Esse endpoint é o equivalente do MongoDB do endpointregisteranterior projetado para PostgreSQL. Ele usa os métodosinsertOnedo driver do MongoDB para interagir com o banco de dados. Enquanto a implementação do PostgreSQL usa uma instrução SQL INSERT para inserir novos dados, a implementação do MongoDB usa o métodoinsertOne para inserir novos dados em uma coleção.
Login:
1app.post('/login', async (req, res) => {
2 const { email, password } = req.body;
3  const user = await usersCollection.findOne({ email });
4
5  let validPass = false;
6
7  if (user) validPass = await bcrypt.compare(password, user.password);
8
9  if (!validPass) return res.status(400).json({ message: 'Invalid credentials' });
10
11    const token = jwt.sign({ sub: user._id, email: user.email }, SECRET_KEY, { expiresIn: '1h' });
12    res.status(200).json({ token });
13});
Esse endpoint é o equivalente do MongoDB do endpoint/loginanterior projetado para PostgreSQL. Ele usa os métodosfindOnedo driver do MongoDB para interagir com o banco de dados. Enquanto a implementação do PostgreSQL usa pool.query para executar uma instrução SQL SELECT para localizar uma linha de usuário na tabela, a implementação do MongoDB usa usersCollection.findOne para localizar um documento do usuário na coleção.
No MongoDB, o método findOne utiliza um objeto JSON para especificar a condição de consulta, que é análoga à cláusula ONDE em SQL. No SQL, users é o nome da tabela que está sendo consultada, semelhante a uma coleção no MongoDB.
Middleware para autenticar usuários:
1const authenticateToken = (req, res, next) => {
2 const token = req.header('Authorization');
3 if (!token) return res.status(401).json({ message: 'Access Denied' });
4 const verified = jwt.verify(token.split(" ")[1], SECRET_KEY);
5    req.user = verified;
6    next();
7};
Aqui, estamos usando a mesma função que usamos no exemplo anterior.
Criar contato:
1app.post('/contacts', authenticateToken, async (req, res) => {
2 const { name, phone, email } = req.body;
3 const contact = { name, phone, email, user_id: req.user.sub, createdAt: new Date().toISOString() };
4 const result = await contactsCollection.insertOne(contact);
5    res.status(201).json(contact);
6});
Esse endpoint é a versão MongoDB do endpoint POST /contactanterior que criamos para o PostgreSQL. Em vez de usar comandos SQL como pool.query para adicionar uma linha de contato a uma tabela, ele usa o método ContactCollection.insertOne do MongoDB para adicionar um documento de contato a uma coleção.
A conversão req.user.id para ObjectId garante que o ID do usuário esteja formatado corretamente e possa ser consultado e indexado com eficiência no MongoDB. Isso é importante, pois precisaremos realizar operações que envolvam a correspondência ou referência a esse ID no banco de dados.
Obter contato por ID:
1app.get('/contacts/:id', authenticateToken, async (req, res) => {
2 const { id } = req.params;
3 const contact = await contactsCollection.findOne({ _id: new ObjectId(id), user_id: req.user.sub });
4 if (!contact) return res.status(404).json({ message: 'Contact not found' });
5    res.status(200).json(contact);
6});
Esse endpoint é o equivalente do MongoDB do endpoint GET /contacts/:idanterior projetado para PostgreSQL. Enquanto a implementação PostgreSQL usa pool.query para executar uma declaração SQL SELECT  e a cláusulaWHERE para localizar uma linha de contato na tabela, a implementação do MongoDB usa o contactsCollection.findOne para localizar um documento de contato na coleção e retorna o documento encontrado.
O PostgreSQL usa diretamente os parâmetrosid e user_id na query SQL, enquanto o MongoDB converte id e user_id em ObjectId para corresponder ao formato de ID do documento do MongoDB.
Contato de atualização:
1app.put('/contacts/:id', authenticateToken, async (req, res) => {
2 const { id } = req.params;
3 const { name, phone, email } = req.body;
4 const contact = await contactsCollection.findOneAndUpdate(
5{ _id: new ObjectId(id), user_id: req.user.sub },
6{ $set: req.body },
7{ returnOriginal: false }
8      );
9 if (!contact) return res.status(404).json({ message: 'Contact not found or not authorized' });
10    res.status(200).json(contact);
11});
Esse endpoint é o equivalente do MongoDB do endpoint PUT /contactsanterior projetado para PostgreSQL. Enquanto a implementação do PostgreSQL usa pool.query para executar uma declaração SQL UPDATE  e uma cláusulaWHERE para atualizar o contato na tabela contacts , a implementação do MongoDB usa o métodofindOneAndUpdate com $set para atualizar o documento na coletacontacts.
Excluir contato:
1app.delete('/contacts/:id', authenticateToken, async (req, res) => {
2 const { id } = req.params;
3 const contact = await contactsCollection.deleteOne({ _id: new ObjectId(id), user_id: req.user.sub });
4 if (!contact.deletedCount) return res.status(404).json({ message: 'Contact not found or not authorized' });
5    res.status(200).json(contact.value);
6});
Esse endpoint é o equivalente do MongoDB do endpoint DELETE /contactanterior projetado para PostgreSQL. Enquanto a implementação do PostgreSQL usa pool.query para executar uma declaração SQL DELETE  e uma cláusulaWHERE para excluir o contato na tabelacontacts, a implementação do MongoDB usa o métododeleteOne para excluir o documento na collectioncontacts collection.
No MongoDB, a query é feita usando objetos semelhantes a JSON. O equivalente da cláusula ONDE é o objeto de query passado para métodos como findOne, deleteOne etc.
Adicionar taxa de chamada:
1app.post('/contacts/:id/rates', authenticateToken, async (req, res) => {
2 const { id } = req.params;
3 const { description } = req.body;
4 const rate = { description, createdAt: new Date().toISOString(), user_id: new ObjectId(req.user.id) };
5 const result = await contactsCollection.updateOne(
6{ _id: new ObjectId(id), user_id: req.user.sub },
7{ $push: { rates: rate } }
8    );
9 if (result.matchedCount === 0) return res.status(404).json({ message: 'Contact not found ' });
10    res.status(201).json(rate);
11});
Esse endpoint é o equivalente do MongoDB do endpoint POST /contacts/:id/ratesanterior projetado para PostgreSQL. Enquanto a implementação do PostgreSQL usa pool.query para executar uma declaração SQL INSERT INTO para inserir uma linha de taxa na tabela, a implementação do MongoDB usa o contactsCollection.updateOne para adicionar uma taxa a um contato, que agora atualizará o documento de contato enviando um nova taxa na array de taxas incorporada.
Ao incorporar as taxas nos contatos, você evita a necessidade de junções (como $lookup), o que pode melhorar o desempenho da consulta, especialmente para operações de leitura pesada. Agora, todas as informações relevantes sobre um contato, incluindo suas taxas, são armazenadas juntas em um único documento.
Obter contatos:
1app.get("/contacts", authenticateToken, async (req, res) => {
2 let { startDate, endDate } = req.query;
3
4 if (!endDate) {
5endDate = new Date().toISOString();
6} else {
7endDate = new Date(endDate).toISOString();
8  }
9
10 if (!startDate) {
11 const now = new Date();
12 const pastDate = new Date(now);
13pastDate.setDate(now.getDate() - 7);
14
15    startDate = pastDate.toISOString();
16} else {
17startDate = new Date(startDate).toISOString();
18  }
19
20 const contacts = await contactsCollection
21    .aggregate([
22      {
23 $match: {
24 createdAt: {
25 $gte: startDate,
26 $lte: endDate,
27          },
28 user_id: req.user.sub
29        },
30      },
31      {
32 $lookup: {
33 from: "users",
34 localField: "user_id",
35 foreignField: "_id",
36 as: "user",
37        },
38      },
39      {
40 $addFields: {
41 call_rate: { $size: { $ifNull: ["$rates", []] } },
42        },
43      },
44{ $sort: { call_rate: -1 } },
45    ])
46    .toArray();
47
48  res.status(200).json(contacts);
49});
Esse endpoint é o equivalente do MongoDB do endpoint GET anterior /contacts projetado para PostgreSQL. Enquanto a implementação do PostgreSQL usa uma query SQL com JOIN declarações , WHERE cláusula , GROUP BY e ORDER BY para executar operações (correspondência, união, adição de campos, classificação) na contacts tabela , a implementação do MongoDB usa o aggregate método para executar operações semelhantes na contacts collection .
Um pipeline de agregação no MongoDB é uma estrutura que passa documentos para um pipeline de vários estágios que pode transformá-los e gerar resultados agregados. Cada estágio do pipeline executa uma operação nos documentos de entrada e passa o resultado para o próximo estágio.
Esse pipeline de agregação filtra os contatos com base em sua data de criação e no ID do usuário autenticado, une a collection de contatos à collection de usuários para buscar detalhes do usuário, une a collection de contatos à collection de taxas para buscar detalhes das taxas e, em seguida, adiciona um novo campo -- - call_rate --- para contar o número de taxas por contato e classificar os contatos por call_rate em ordem decrescente.
Em comparação com a declaração SQL, você não precisa usar dois JOINs. Portanto, o desempenho é melhor.

Migrando os dados

Agora, vamos falar sobre como usar o Conversor de query do MongoDB para migrar suas queries SQL para a API de query do MongoDB.
O MongoDB fornece uma ferramenta chamada Relational Migrator que permite migrar suas queries SQL para a API de query do MongoDB com facilidade. Ele também aborda desafios comuns de migração e modelagem de dados para fornecer uma transição suave para o MongoDB.
Baixar o Relational Migrator para experimentar você mesmo.
Antes de utilizar o conversor de query, você deve iniciar sessão na sua conta Atlas no Relational Migrator. Para detalhes, consulte Iniciar sessão com Atlas.
  • Abra a aplicação Relational Migrator no seu PC e inicie sessão com Atlas. 
  • Conecte-se ao seu banco de dados Postgres.
  • Selecione as tabelas que deseja migrar.
  • Defina seu esquema da seguinte forma:
Definir captura de tela do esquema inicial
Em seguida, nomeie seu projeto.
Gere o esquema MongoDB a partir da tabela do banco de dados Postgres importada da seguinte forma:
Captura de tela do Relational Migrator Na aba Geração de código, clique no painel Conversor de query.
Clique no botão Colar query SQL para acessar o editor do conversor de query.
Captura de tela do Relational Migrator
Aqui, você pode inserir as queries SQL que deseja converter e clicar em Converter para convertê-las em queries do MongoDB.

Importar dados usando o MongoDB Compass

O MongoDB Compass é uma interface gráfica de usuário para MongoDB e é totalmente gratuito para instalar no Mac, Windows e Linux. Você pode importar dados JSON ou CSV para o MongoDB via MongoDB Compass.
Tela de criação de nova collection do Compass
Para importar dados para uma collection, conecte-se ao cluster de banco de dados usando a connection string do Atlas, crie um banco de dados e uma collection, e navegue até a exibição detalhada da collection selecionando a collection na aba Bancos de dados ou clicando na collection na navegação do lado esquerdo .
Em seguida, clique no menu suspenso Adicionar Dados, selecione Importar arquivo JSON ou CSV, selecione o tipo de arquivo apropriado e clique em Importar. Após a importação bem-sucedida, a caixa de diálogo é fechada e o Compass exibe a página de coleção que contém os documentos recém-importados.

Importar dados usando MongoImport

Para importar dados usando mongoimport, instale as MongoDB database, um conjunto de utilitários de linha de comando para trabalhar com o MongoDB e, em seguida, execute mongoimport a partir da linha de comando do sistema.
Aqui está um exemplo de importação de dados via mongoimport:
1mongoimport mongodb+srv://<cluster-username>:<cluster-password>@cluster0.33t5arb.mongodb.net/Node-API?retryWrites=true&w=majority&appName=Cluster0 --collection=user --file=users.json
Aqui, usamos mongoimport para importar os dados JSON do arquivo users.json para a collection de usuários no banco de dados Node-API.

Importar dados usando a extensão VS Code

Para importar dados usando a extensão VS Code, Go para a aba de extensões no VS Code e procure MongoDB. Você deve ver a extensão do MongoDB para VS Code.
Extensão do MongoDB para VS Code
Depois de instalá-lo com sucesso, você verá um ícone de folha na barra lateral do VS Code. Clique nele e, em conexões, adicione uma nova conexão. Em seguida, clique em Conectar com a cadeia de conexão e passe a cadeia de conexão do cluster de banco de dados.
Você deve ver seu cluster. Passe o mouse sobre seu cluster e clique no ícone de "mais" para criar um novo banco de dados. Isso gerará um arquivo de playground onde você pode adicionar o seguinte script para criar um banco de dados, collection e importar dados:
1// Select the database to use.
2use('database-name');
3// Insert documents into the users collection.
4db.getCollection('users').insertMany("Copy and paste the content of your JSON file here");

Testando a migração

Use o Postman ou qualquer ferramenta de teste da API para testar todos os endpoints atualizados com as queries migradas e garantir que a migração funcione conforme o esperado.

Conclusão

A migração de um aplicativo Node.js de um banco de dados SQL para o MongoDB pode ser simples e eficiente quando feita com um recurso bem estruturado. Neste tutorial, demos uma olhada em configurar o MongoDB, migrar as queries SQL e executar a migração de dados com o MongoDB Compass, MongoImport e a extensão MongoDB for VS Code.  
Seguindo a abordagem estruturada no tutorial, você pode migrar com sucesso seu aplicativo Node.js de um banco de dados SQL para o MongoDB.
Perguntas? Quer compartilhar o que você está construindo?Em seguida, acesse a Comunidade de desenvolvedores doMongoDB.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

Uma leve introdução às listas vinculadas com o MongoDB


Apr 02, 2024 | 13 min read
Tutorial

Tutorial de ponta a ponta do Kafka para MongoDB Atlas


Jun 07, 2023 | 6 min read
Tutorial

Chat em tempo real em um jogo de Phaser com MongoDB e Socket.io


Feb 03, 2023 | 11 min read
Início rápido

Início rápido: tipos de dados BSON - Decimal128


Sep 23, 2022 | 2 min read
Sumário