Documentos e coleções no MongoDB: estrutura e consultas
Aprenda como documentos BSON e coleções funcionam, consulte objetos e arrays e aplique validação de schema com o driver oficial do MongoDB.
Um documento é o registro que o MongoDB guarda; uma coleção reúne
documentos do mesmo contexto. Nesta lição, você vai criar a coleção livros,
armazenar objetos e arrays, consultar campos internos e ver o banco recusar um
estoque negativo.
Em termos técnicos, o documento é uma sequência de pares campo–valor codificada em BSON. Em termos práticos, ele se parece com o objeto que sua aplicação já usa, mas ganha identidade, tipos próprios e persistência no servidor.
O fichário ajuda, até onde ajuda
Pense no catálogo físico da Livraria Horizonte. Cada ficha descreve um livro; ela pode ter título, preço, estoque, etiquetas de categoria e um quadro com os dados da editora. O conjunto de fichas forma o fichário. No MongoDB, a ficha é o documento e o fichário é a coleção.
O campo _id é o código único escrito na ficha. categorias é uma lista de
etiquetas. editora é um pequeno quadro incorporado na ficha. Essa imagem
explica por que informações lidas juntas podem ficar juntas.
Mas uma coleção não é um móvel que o banco percorre sempre do começo ao fim. MongoDB usa índices, cache e planos de consulta. Além disso, uma ficha de papel não cresce indefinidamente; um documento também não deve receber um array sem limite só porque BSON aceita arrays. A analogia localiza as partes, não decide a modelagem por você.
Se esses nomes ainda estiverem soltos, volte ao guia de MongoDB, que separa servidor, database, coleção e driver antes de chegar ao código.
Prepare o mesmo laboratório
Use o MongoDB 8.0.28 local descrito no guia. Em uma pasta vazia, instale o
driver oficial e execute arquivos .mjs com Node:
npm init -y
npm install mongodb@7.5.0No início de documentos.mjs, conecte e recrie um database exclusivo. O
dropDatabase() é destrutivo; aqui ele é aceitável porque o nome
devclub_documentos pertence somente ao laboratório. Nunca troque esse nome
por uma base real para “testar mais rápido”.
import { MongoClient } from "mongodb";
const uri = process.env.MONGODB_URI ?? "mongodb://127.0.0.1:27017";
const client = new MongoClient(uri);
await client.connect();
const db = client.db("devclub_documentos");
await db.dropDatabase();
console.log({ database: db.databaseName, estado: "limpo" });Ao terminar o arquivo, acrescente await client.close(). Em código de produção,
prefira try/finally; aqui manteremos os passos próximos para enxergar o estado
que cada operação cria.
Crie uma coleção que sabe o que recusar
Inserir num nome inexistente pode criar uma coleção automaticamente. Vamos
criá-la de forma explícita porque precisamos de validação. $jsonSchema exige
os três campos centrais e restringe o estoque a inteiro não negativo:
await db.createCollection("livros", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["titulo", "preco", "estoque"],
properties: {
titulo: { bsonType: "string" },
preco: {
bsonType: ["double", "int", "long", "decimal"],
minimum: 0,
},
estoque: { bsonType: "int", minimum: 0 },
},
},
},
});
console.log(await db.listCollections({}, { nameOnly: true }).toArray());bsonType fala a língua do banco. O número 39.9 enviado pelo Node chega como
double; o inteiro pequeno 8 chega como int. Por isso preço aceita uma
lista de tipos numéricos e estoque exige inteiro. Num sistema financeiro,
defina uma convenção de centavos ou Decimal128 em vez de misturar tipos sem
controle.
Validação não transforma MongoDB em banco relacional nem cria relacionamentos. Ela protege o formato de cada documento que entra ou muda na coleção.
Insira documentos com lista e objeto interno
insertMany() recebe um array de documentos. Os ids textuais tornam o
laboratório repetível; se _id fosse omitido, o driver geraria ObjectId.
const livros = db.collection("livros");
const resultado = await livros.insertMany([
{
_id: "livro-1",
titulo: "JavaScript do zero",
preco: 39.9,
estoque: 8,
categorias: ["programação", "javascript"],
editora: { nome: "Código Aberto", cidade: "São Paulo" },
},
{
_id: "livro-2",
titulo: "Node.js na prática",
preco: 54.5,
estoque: 5,
categorias: ["programação", "node"],
editora: { nome: "Código Aberto", cidade: "São Paulo" },
},
{
_id: "livro-3",
titulo: "Design para quem programa",
preco: 46,
estoque: 3,
categorias: ["design", "interface"],
editora: { nome: "Traço", cidade: "Recife" },
},
]);
console.log({ inseridos: resultado.insertedCount });Um documento pode não ter todos os campos do outro. A validação só exige os
campos declarados em required. Isso é schema flexível, não ausência de
schema: seu código, suas consultas e suas regras ainda pressupõem um formato.
Consulte um campo aninhado e um valor do array
Como encontrar livros de programação cuja editora fica em São Paulo? A notação
editora.cidade atravessa o documento incorporado. Comparar
categorias: "programação" encontra arrays que contêm esse elemento:
const encontrados = await livros
.find(
{
"editora.cidade": "São Paulo",
categorias: "programação",
},
{
projection: {
_id: 0,
titulo: 1,
"editora.nome": 1,
},
},
)
.sort({ titulo: 1 })
.toArray();
console.log(encontrados);O filtro decide quem entra. A projeção decide o que sai. find() cria um
cursor; sort() acrescenta ordenação; toArray() consome o cursor. Para um
resultado potencialmente enorme, use limite, paginação por cursor ou iteração;
não carregue tudo em memória sem medir.
Atualize sem substituir o documento inteiro
O preço e as categorias não devem sumir quando o estoque muda. Por isso usamos
operadores de atualização. $inc soma 2 ao estoque e $set cria um campo
interno sem substituir todo o objeto editora:
const alteracao = await livros.updateOne(
{ _id: "livro-1" },
{
$inc: { estoque: 2 },
$set: { "editora.site": "codigoaberto.dev" },
},
);
console.log({
encontrados: alteracao.matchedCount,
alterados: alteracao.modifiedCount,
});matchedCount responde se o filtro encontrou documento. modifiedCount
responde se houve mudança. Eles podem ser diferentes: definir um campo com o
valor que ele já possui encontra o documento, mas não altera seu estado.
Confira o pedaço afetado, em vez de confiar apenas na contagem:
const conferido = await livros.findOne(
{ _id: "livro-1" },
{ projection: { _id: 0, estoque: 1, editora: 1 } },
);
console.log(conferido);Você verá mais filtros e operadores na próxima aula de CRUD MongoDB com Node.js.
Provoque a regra de estoque
Agora teste a porta fechada, não só o caminho que passa. A tentativa abaixo tem
todos os campos obrigatórios, mas viola minimum: 0:
try {
await livros.insertOne({
titulo: "Livro inválido",
preco: 20,
estoque: -1,
});
} catch (erro) {
console.log({
erro: "documento recusado",
codigo: erro.code,
motivo: "estoque abaixo de zero",
});
}O código 121 é DocumentValidationFailure. Em uma API, registre os detalhes
técnicos e transforme a falha em resposta útil. Não dependa da frase integral
do servidor como contrato: versões e regras diferentes podem produzir detalhes
distintos; o código e a validação que você definiu são as pistas estáveis.
Missão: acrescente um formato sem abandonar o contrato
Cadastre livro-4 como e-book. Ele deve manter titulo, preco e estoque,
mas pode adicionar formatoArquivo: "epub" e tamanhoMB: 4.2. Depois faça uma
consulta que devolva apenas título e formato:
await livros.insertOne({
_id: "livro-4",
titulo: "APIs sem mistério",
preco: 34.9,
estoque: 999,
formatoArquivo: "epub",
tamanhoMB: 4.2,
});
console.log(await livros.findOne(
{ formatoArquivo: "epub" },
{ projection: { _id: 0, titulo: 1, formatoArquivo: 1 } },
));
await client.close();A missão termina quando o quarto documento entra, a projeção não traz preço nem
estoque e uma tentativa com estoque: -1 continua falhando. Assim você prova as
duas ideias ao mesmo tempo: a coleção aceita variação útil e preserva a regra
que não pode variar. Quando a dúvida for onde incorporar ou separar dados,
avance para modelagem MongoDB.
Perguntas frequentes
Documento MongoDB é igual a objeto JavaScript?
Uma coleção obriga todos os documentos a ter os mesmos campos?
Para que serve o campo _id?
Como consulto um campo dentro de outro documento?
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
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
- MongoDB Manual — Introduction to MongoDB — mongodb.com
- MongoDB Manual — Documents — mongodb.com
- MongoDB Manual — Collections — mongodb.com
- MongoDB Manual — Schema Validation — mongodb.com


