Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIniciantecódigo testado

CRUD no MongoDB com Node.js e o driver oficial

Faça create, read, update e delete no MongoDB usando Node.js, com filtros, projeção, operadores, contagens reais e erro de _id duplicado.

Rodolfo Mori5 min de leitura

CRUD é o conjunto de operações para criar, ler, atualizar e remover dados. Nesta lição, você vai executar as quatro com o driver oficial do MongoDB para Node.js e confirmar cada mudança por contagens e consultas reais.

Os nomes técnicos no driver são insert, find, update e delete. A sigla serve como mapa mental; o método específico diz quantos documentos a operação pretende atingir, como updateOne() ou updateMany().

Quatro pedidos diferentes no balcão

Imagine o balcão da Livraria Horizonte. “Cadastre estes livros” cria fichas; “mostre os ativos abaixo de R$ 50” lê fichas; “baixe duas unidades deste id” altera uma ficha; “retire este item inativo” remove uma ficha.

O atendente não recebe apenas um verbo. Ele recebe também um critério. No MongoDB, o filtro cumpre esse papel. { _id: "livro-1" } é um pedido bem delimitado; {} aceita qualquer documento. O limite da analogia é que métodos como updateMany() e deleteMany() trabalham sobre conjuntos sem pedir confirmação humana. Um filtro vazio pode atingir a coleção inteira.

Antes de avançar, confira documentos e coleções se _id, BSON e campos internos ainda não estiverem claros.

Conecte uma vez e garanta o fechamento

Instale o pacote mongodb 7.5.0 em uma pasta vazia:

bash
npm init -y
npm install mongodb@7.5.0
added 12 packages

Crie crud.mjs. O database exclusivo deixa dropDatabase() seguro dentro deste laboratório. try/finally garante que o processo libere a conexão mesmo quando provocarmos o erro do fim da aula:

js
import { MongoClient } from "mongodb";

const uri = process.env.MONGODB_URI ?? "mongodb://127.0.0.1:27017";
const client = new MongoClient(uri);

try {
  await client.connect();
  const db = client.db("devclub_crud");
  await db.dropDatabase();
  console.log(await db.command({ ping: 1 }));

  // Os próximos exemplos entram aqui.
} finally {
  await client.close();
}
{ ok: 1 }

Criar MongoClient não comprova a conexão. connect() inicia a comunicação e ping fornece uma evidência explícita. Em uma API, mantenha um cliente reutilizável; abrir outro por requisição cria conexões e latência sem necessidade.

Create: insira um conjunto conhecido

Use ids determinados para repetir o teste. insertMany() devolve um resultado de escrita, não os documentos completos:

js
const livros = db.collection("livros");

const criacao = await livros.insertMany([
  {
    _id: "livro-1",
    titulo: "JavaScript do zero",
    preco: 39.9,
    estoque: 8,
    ativo: true,
  },
  {
    _id: "livro-2",
    titulo: "Node.js na prática",
    preco: 54.5,
    estoque: 5,
    ativo: true,
  },
  {
    _id: "livro-3",
    titulo: "CSS sem sustos",
    preco: 29.9,
    estoque: 0,
    ativo: false,
  },
]);

console.log({ operacao: "create", inseridos: criacao.insertedCount });
{ operacao: 'create', inseridos: 3 }

insertedCount: 3 é a confirmação mensurável. Em uma inserção ordenada, um erro interrompe os itens seguintes. Operações em lote têm opções próprias; não presuma que uma lista inteira entrou sem ler o resultado ou tratar a falha.

Read: filtro, projeção e ordenação têm trabalhos diferentes

A vitrine quer livros ativos abaixo de R$ 50. ativo e $lt formam o filtro; a projeção remove _id e limita os campos; sort() define a ordem:

js
const encontrados = await livros
  .find(
    { ativo: true, preco: { $lt: 50 } },
    { projection: { _id: 0, titulo: 1, preco: 1 } },
  )
  .sort({ preco: 1 })
  .toArray();

console.log({ operacao: "read", livros: encontrados });
{ operacao: 'read', livros: [ { titulo: 'JavaScript do zero', preco: 39.9 } ] }

$lt significa “menor que”. Se quisesse incluir 50, seria $lte. A ordenação 1 é crescente e -1 é decrescente. Esses símbolos são parte da MongoDB Query API, não nomes inventados pelo Node.

Use findOne() quando a intenção é receber no máximo um documento. Ele retorna null quando nada combina; não lança um erro de “não encontrado”. Sua rota é que decide se null deve virar HTTP 404.

Update: coloque a regra dentro do filtro

Uma venda de duas unidades só pode acontecer se houver pelo menos duas. Essa condição precisa participar da mesma operação que baixa o estoque:

js
const alteracao = await livros.updateOne(
  { _id: "livro-1", estoque: { $gte: 2 } },
  {
    $inc: { estoque: -2 },
    $set: { atualizadoEm: new Date("2026-08-22T12:00:00.000Z") },
  },
);

console.log({
  operacao: "update",
  encontrados: alteracao.matchedCount,
  alterados: alteracao.modifiedCount,
});
{ operacao: 'update', encontrados: 1, alterados: 1 }

MongoDB garante atomicidade da escrita no nível de um documento. O filtro vê o estoque e $inc o muda como uma operação única. Isso evita o intervalo entre “li 8” e “gravei 6” no código da aplicação.

Contagem não substitui conferência quando você está aprendendo. Leia o estado final:

js
console.log(await livros.findOne(
  { _id: "livro-1" },
  { projection: { _id: 0, titulo: 1, estoque: 1 } },
));
{ titulo: 'JavaScript do zero', estoque: 6 }

Se matchedCount fosse zero, poderia ser id inexistente ou estoque insuficiente. Uma API pode fazer uma leitura complementar para distinguir as mensagens, mas não deve desfazer a segurança do filtro condicional.

Quando uma operação precisa mudar vários documentos como unidade, a fronteira muda. A modelagem MongoDB mostra uma transação entre estoque e pedido, além de explicar quando incorporar evita essa coordenação.

Delete: o filtro deve descrever o motivo da remoção

Queremos retirar somente o livro já marcado como inativo. Colocar ativo: false no filtro impede que o mesmo comando remova acidentalmente um livro reativado por outra parte do sistema:

js
const remocao = await livros.deleteOne({
  _id: "livro-3",
  ativo: false,
});

console.log({
  operacao: "delete",
  removidos: remocao.deletedCount,
  restantes: await livros.countDocuments(),
});
{ operacao: 'delete', removidos: 1, restantes: 2 }

Em sistemas com auditoria, exclusão física pode não ser a regra de negócio. Um campo como arquivadoEm preserva histórico, mas também exige que consultas normais filtrem os registros arquivados. “Soft delete” não é automaticamente mais seguro; ele muda as obrigações do sistema.

Reproduza o _id duplicado

MongoDB cria um índice único para _id. Tentar cadastrar outro documento com livro-1 faz o servidor rejeitar a escrita com código 11000:

js
try {
  await livros.insertOne({
    _id: "livro-1",
    titulo: "Cópia",
    preco: 10,
    estoque: 1,
  });
} catch (erro) {
  console.log({
    erro: "_id duplicado",
    codigo: erro.code,
    indice: "_id_",
  });
}
{ erro: '_id duplicado', codigo: 11000, indice: '_id_' }

Não “resolva” criando outro id silenciosamente se esse id representa uma operação repetida. Às vezes, o duplicado é exatamente a proteção contra cobrar ou processar o mesmo pedido duas vezes. Entenda a identidade antes de tratar todo 11000 como mero inconveniente.

Driver oficial e Mongoose não são sinônimos

O pacote usado aqui é o MongoDB Node.js Driver oficial. Ele trabalha com coleções, filtros, cursores, sessões e resultados próximos da API do banco. Mongoose é um ODM: adiciona modelos, schemas na aplicação, hooks e outras convenções.

Minha ordem de aprendizado é driver primeiro. Assim, matchedCount, $inc, projeção e índice continuam reconhecíveis quando uma abstração gera a consulta errada. Depois, adote Mongoose se modelos e middleware trouxerem valor para o time. O banco ainda precisa de regras próprias para proteger escritas vindas de scripts, jobs ou outras aplicações.

Para transformar listas em relatórios, o próximo mecanismo é o aggregation pipeline. Para evitar que consultas frequentes examinem a coleção inteira, estude índices MongoDB.

Missão: uma venda que não deixa estoque negativo

Acrescente uma segunda chamada a updateOne(), pedindo 99 unidades do livro-2, e imprima resultado e estoque final:

js
const tentativa = await livros.updateOne(
  { _id: "livro-2", estoque: { $gte: 99 } },
  { $inc: { estoque: -99 } },
);

const livro2 = await livros.findOne(
  { _id: "livro-2" },
  { projection: { _id: 0, estoque: 1 } },
);

console.log({
  encontrados: tentativa.matchedCount,
  alterados: tentativa.modifiedCount,
  estoqueFinal: livro2.estoque,
});
{ encontrados: 0, alterados: 0, estoqueFinal: 5 }

A missão termina quando a operação recusa a baixa e o estoque continua 5. Troque 99 por 3 e repita: as contagens devem virar 1 e o estoque, 2. Você não está apenas praticando sintaxe; está provando que o filtro carrega uma regra de negócio verificável.

  • mongodb
  • node.js
  • crud
  • mongodb driver
  • banco de dados

Perguntas frequentes

O que significa CRUD no MongoDB?
CRUD reúne create, read, update e delete. No driver Node.js, operações comuns são insertOne ou insertMany, find ou findOne, updateOne ou updateMany e deleteOne ou deleteMany.
Preciso abrir uma conexão para cada operação?
Não. Em uma aplicação longa, crie e reutilize um MongoClient durante a vida do processo. Este laboratório usa um único cliente e o fecha no finally quando o script termina.
Qual a diferença entre find e findOne?
findOne devolve um documento ou null. find devolve um cursor que pode ser ordenado, limitado e consumido com toArray ou iteração assíncrona.
O driver oficial substitui Mongoose?
O driver cobre comunicação e operações do MongoDB. Mongoose adiciona ODM, modelos, middleware e validação na aplicação. Escolha essa camada quando o benefício superar a abstração extra, não por obrigação.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em MongoDB 8.0.28, MongoDB Node.js Driver 7.5.0, Node 26.3.0 e Docker 29.5.3, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. MongoDB Node.js Driver — CRUD Operations — mongodb.com
  2. MongoDB Node.js Driver — Insert Documents — mongodb.com
  3. MongoDB Node.js Driver — Find Documents — mongodb.com
  4. MongoDB Manual — CRUD Operations — mongodb.com

Continue por aqui