MongoDB em produção
- ⬜🧩 NoSQL: mental model 2026(NoSQL + Vector Databases)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Quando Mongo é a escolha certa
| Situação | Documento cabe? | Por quê |
|---|---|---|
| Esquema que varia entre registros | Sim | Campo opcional não custa coluna nula |
| Dado lido sempre junto | Sim | Uma leitura traz o agregado inteiro, sem junção |
| Relação muitos-para-muitos consultada dos dois lados | Não | Ou você duplica, ou faz junção — e junção não é a força aqui |
| Transação entre várias entidades | Com cuidado | Existe, e é mais cara que num relacional |
| Relatório com agregação complexa | Depende | O canal de agregação é poderoso e mais difícil de otimizar que SQL |
| Consistência forte entre documentos | Não | Se você precisa disso o tempo todo, o modelo é outro |
MongoDB vale a pena quando o domínio tem estrutura variável por natureza (configs de tenant, catálogo heterogêneo, eventos semi-estruturados) e o padrão de acesso é dominado por find por chave + aggregation. Se você está reescrevendo Postgres com joins em Mongo, errou a escolha.
Aggregation pipeline real
Abaixo um pipeline que responde "top 5 categorias por receita nos últimos 30 dias, com ticket médio e quantidade de pedidos únicos". Esse é o tipo de query que mostra o poder do aggregation framework.
db.orders.aggregate([
// 1. Filtra janela de 30 dias (usa indice em createdAt)
{ $match: {
status: 'paid',
createdAt: { $gte: new Date(Date.now() - 30 * 864e5) }
}},
// 2. Abre array de items (1 doc por item)
{ $unwind: '$items' },
// 3. Agrupa por categoria
{ $group: {
_id: '$items.category',
receita: { $sum: { $multiply: ['$items.qty', '$items.price'] }},
pedidos: { $addToSet: '$_id' },
ticketTotal: { $sum: '$total' },
docs: { $sum: 1 }
}},
// 4. Calcula metricas derivadas
{ $project: {
categoria: '$_id',
receita: 1,
pedidosUnicos: { $size: '$pedidos' },
ticketMedio: { $divide: ['$ticketTotal', { $size: '$pedidos' }] },
_id: 0
}},
// 5. Ordena e limita
{ $sort: { receita: -1 }},
{ $limit: 5 }
], { allowDiskUse: true });Use explain("executionStats") em todo pipeline novo. Procure por COLLSCAN — sinal de índice ausente — e por estágios que não aproveitam o índice inicial (depois do primeiro $match, o índice perde efeito).
Schema design: embed vs reference
// Embed (leitura junta, bound conhecido)
{
_id: ObjectId('...'),
title: 'Post sobre Mongo',
author: { text: 'Fernando' }, // embed: raramente muda
tags: ['nosql', 'mongo'], // bounded
comments: [ // RISCO se viral
{ user: 'u2', text: 'bom', at: ISODate() }
]
}
// Reference (unbounded ou reuso)
// posts:
{ _id: ObjectId('...'), title: '...', authorId: 'u1' }
// comments:
{ _id: ObjectId('...'), postId: 'p1', user: 'u2', text: 'bom' }Arrays ilimitados dentro de documento são armadilha clássica. Se o array pode crescer sem teto (comments em post viral, events por usuário), use bucketing ou coleção separada.
Qual é o critério para embutir um documento relacionado em vez de referenciá-lo?
Índices e production hygiene
// Compound index segue regra ESR: Equality, Sort, Range
db.orders.createIndex(
{ status: 1, createdAt: -1, total: 1 },
{ background: true, name: 'orders_status_date_total' }
);
// TTL index para dados efemeros
db.sessions.createIndex(
{ lastSeen: 1 },
{ expireAfterSeconds: 86400 }
);
// Checar indices nao usados (em producao real)
db.orders.aggregate([{ $indexStats: {} }]);Write concern e durability
Dados financeiros: sempre w: "majority" + j: true. w:1 aceita perda silenciosa em failover. Read concern "majority" para consistência entre réplicas.
Mongo é excelente em document domain com acesso por chave. Ruim em joins complexos. Saiba diferenciar.
Perguntas frequentes
❓ Embutir documento ou referenciar?
❓ Índice composto no documento segue as mesmas regras do relacional?
❓ Como escalar leitura e escrita?
Fixando
Qual característica do pipeline de agregação exige atenção em produção?
Qual prática de higiene é frequentemente esquecida?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…