<h2>MongoDB com Node.js: Mongoose, Aggregation Pipeline e Índices</h2>
<p>Trabalhar com MongoDB em Node.js é uma experiência poderosa quando você domina as ferramentas certas. Neste guia, vamos explorar três pilares fundamentais: o Mongoose como ODM (Object Document Mapper), o Aggregation Pipeline para transformações complexas de dados, e os índices para otimização de performance. Esses conhecimentos são essenciais para construir aplicações escaláveis e eficientes.</p>
<h3>Configuração Inicial e Conceitos Fundamentais</h3>
<p>Antes de começar, instale as dependências necessárias:</p>
<pre><code class="language-bash">npm install mongoose dotenv</code></pre>
<p>O Mongoose é uma abstração que oferece validação de schema, middlewares e métodos auxiliares poderosos. Ao contrário do MongoDB puro, você trabalha com schemas tipados, o que reduz bugs em produção. Veja como criar uma conexão e definir um schema básico:</p>
<pre><code class="language-javascript">// config/database.js
const mongoose = require('mongoose');
mongoose.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
});
const userSchema = new mongoose.Schema({
nome: { type: String, required: true, trim: true },
email: { type: String, required: true, unique: true, lowercase: true },
idade: { type: Number, min: 18, max: 120 },
criado_em: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
module.exports = User;</code></pre>
<p>Aqui definimos validações direto no schema: campos obrigatórios, tipos de dados, transformações (trim, lowercase) e valores padrão. Isso simplifica drasticamente a lógica de negócio na sua aplicação.</p>
<h2>Mongoose: Operações CRUD e Validações Avançadas</h2>
<h3>Criando e Consultando Documentos</h3>
<p>O Mongoose oferece métodos encadeáveis para queries que melhoram a legibilidade do código. Veja operações comuns:</p>
<pre><code class="language-javascript">// Criar um novo usuário
const novoUsuario = await User.create({
nome: 'João Silva',
email: 'joao@email.com',
idade: 28
});
// Buscar por ID
const usuario = await User.findById('507f1f77bcf86cd799439011');
// Buscar com múltiplas condições
const usuarios = await User.find({ idade: { $gte: 25 } })
.select('nome email')
.sort({ criado_em: -1 })
.limit(10);
// Atualizar
await User.findByIdAndUpdate(
'507f1f77bcf86cd799439011',
{ idade: 30 },
{ new: true, runValidators: true }
);
// Deletar
await User.findByIdAndDelete('507f1f77bcf86cd799439011');</code></pre>
<h3>Middleware e Hooks Customizados</h3>
<p>O Mongoose permite executar funções antes (pre) e depois (post) de operações específicas. Isso é útil para criptografia, logs e transformações:</p>
<pre><code class="language-javascript">userSchema.pre('save', async function(next) {
if (!this.isModified('senha')) return next();
// Simular hash de senha
this.senha = hashed_${this.senha};
next();
});
userSchema.post('save', function(doc) {
console.log(Usuário ${doc.nome} foi salvo com sucesso);
});</code></pre>
<h2>Aggregation Pipeline: Transformações Poderosas de Dados</h2>
<h3>Estrutura e Casos de Uso</h3>
<p>O Aggregation Pipeline é o coração da análise de dados no MongoDB. Diferente do <code>.find()</code>, ele permite transformações complexas em múltiplos estágios:</p>
<pre><code class="language-javascript">// Exemplo: Agrupar usuários por faixa etária e contar
const relatorio = await User.aggregate([
{
$match: { idade: { $gte: 18 } }
},
{
$group: {
_id: {
$cond: [
{ $lt: ['$idade', 30] },
'Jovem',
'Adulto'
]
},
total: { $sum: 1 },
mediaIdade: { $avg: '$idade' }
}
},
{
$sort: { total: -1 }
}
]);
console.log(relatorio);
// Output: [
// { _id: 'Adulto', total: 15, mediaIdade: 45 },
// { _id: 'Jovem', total: 10, mediaIdade: 25 }
// ]</code></pre>
<h3>Exemplo Prático: Pipeline Completo</h3>
<p>Imagine que você precisa de um relatório de usuários ativos com suas estatísticas. Vamos construir um pipeline realista:</p>
<pre><code class="language-javascript">const estatisticas = await User.aggregate([
// Estágio 1: Filtrar usuários ativos
{ $match: { ativo: true } },
// Estágio 2: Transformar documento
{
$project: {
nome: 1,
email: 1,
faixaEtaria: {
$cond: [
{ $lt: ['$idade', 30] },
'Sub-30',
{ $cond: [{ $lt: ['$idade', 50] }, '30-50', '50+'] }
]
}
}
},
// Estágio 3: Agrupar por faixa
{
$group: {
_id: '$faixaEtaria',
usuarios: { $push: '$nome' },
quantidade: { $sum: 1 }
}
},
// Estágio 4: Ordenar
{ $sort: { quantidade: -1 } }
]);</code></pre>
<p>Esse pipeline é executado no servidor MongoDB, não na aplicação, o que economiza banda e processamento.</p>
<h2>Índices: Otimizando a Performance</h2>
<h3>Criando e Gerenciando Índices</h3>
<p>Índices são fundamentais para queries rápidas em coleções grandes. No Mongoose, você os define no schema:</p>
<pre><code class="language-javascript">const userSchema = new mongoose.Schema({
nome: { type: String, required: true },
email: { type: String, required: true, index: true, unique: true },
idade: { type: Number, index: true },
cidade: String,
criado_em: { type: Date, default: Date.now, index: true }
});
// Índice composto para queries frequentes
userSchema.index({ idade: 1, cidade: 1 });
// Índice texto para busca full-text
userSchema.index({ nome: 'text' });</code></pre>
<h3>Explicando Performance com explain()</h3>
<p>Use o método <code>.explain()</code> para entender como MongoDB executa suas queries:</p>
<pre><code class="language-javascript">// Sem índice - COLLSCAN (varre toda coleção)
const resultadoSemIndice = await User.find({ email: 'teste@email.com' })
.explain('executionStats');
// Com índice - IXSCAN (usa índice)
const resultadoComIndice = await User.find({ email: 'teste@email.com' })
.explain('executionStats');
console.log(resultadoComIndice.executionStats.executionStages.stage);
// Output: 'IXSCAN' (mais rápido)</code></pre>
<blockquote><p><strong>Dica profissional:</strong> Crie índices apenas para campos que você consulta frequentemente. Cada índice consome memória e desacelera inserts. Balance performance de leitura com eficiência de escrita.</p></blockquote>
<h2>Conclusão</h2>
<p>Dominando MongoDB com Node.js, você alcança três objetivos críticos: <strong>validação robusta através do Mongoose</strong>, eliminando classes inteiras de bugs; <strong>transformações eficientes via Aggregation Pipeline</strong>, processando dados no servidor ao invés da aplicação; e <strong>otimização garantida com índices estratégicos</strong>, mantendo queries rápidas mesmo com milhões de registros. Esses conhecimentos formam a base para aplicações production-ready e escaláveis.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://mongoosejs.com/" target="_blank" rel="noopener noreferrer">Mongoose Official Documentation</a></li>
<li><a href="https://docs.mongodb.com/manual/aggregation/" target="_blank" rel="noopener noreferrer">MongoDB Aggregation Framework Guide</a></li>
<li><a href="https://docs.mongodb.com/manual/indexes/" target="_blank" rel="noopener noreferrer">MongoDB Indexing Best Practices</a></li>
<li><a href="https://www.mongodb.com/developer/languages/javascript/" target="_blank" rel="noopener noreferrer">Node.js + MongoDB: The Complete Developer's Guide</a></li>
<li><a href="https://docs.mongodb.com/manual/reference/explain-results/" target="_blank" rel="noopener noreferrer">Performance Tuning with MongoDB Explain</a></li>
</ul>