Nivel 2 · 25 min
Aggregation Pipeline
El aggregation pipeline de MongoDB procesa documentos a través de una secuencia de stages, cada uno transformando los datos. Es la herramienta principal para analytics, reporting y transformaciones de datos complejas en MongoDB.
Stages Core del Pipeline
$match filtra documentos (como WHERE en SQL): ponerlo primero para reducir el working set. Usa índices cuando es el primero en el pipeline. $group agrupa documentos por una expresión _id y calcula acumuladores ($sum, $avg, $max, $min, $push, $addToSet). $project reshapea documentos: incluir/excluir campos, calcular nuevos campos, renombrar campos. $sort ordena documentos. $limit y $skip para paginación. $unwind deconstruye un campo array: crea un documento de salida por elemento del array. $addFields agrega nuevos campos computados sin remover los existentes.
$lookup y $unwind
$lookup realiza un left outer join entre la colección actual y otra colección. La sintaxis básica: from (colección objetivo), localField, foreignField, as (campo de salida array). El resultado de $lookup es un array — incluso para matches únicos. Usá $unwind después de $lookup para aplanar los documentos joined. $lookup con pipeline (ES 3.6+) permite condiciones de join complejas. Nota de performance: $lookup ejecuta una query separada por documento en el pipeline. Asegurate de que el foreignField tenga un índice.
Optimización del Pipeline
MongoDB optimiza automáticamente algunos patrones: stages $match consecutivos se mergean, $sort + $limit se optimiza en un sort top-N. Best practices manuales: poné $match lo antes posible para reducir documentos procesados. Poné $project para eliminar campos innecesarios temprano. Usá $match antes de $unwind para filtrar antes de la expansión del array. allowDiskUse: true habilita el spill a disco para aggregations grandes que superen el límite de 100 MB de memoria.
Code example
db.orders.aggregate([\n {$match: {createdAt: {$gte: new Date(Date.now() - 90*24*60*60*1000)}'}'} ,\n {$lookup: {from: "users", localField: "userId", foreignField: "_id", as: "user"}'}',\n {$unwind: "$user"}',\n {$group: {_id: "$userId", totalValue: {$sum: "$amount"}, orderCount: {$sum: 1}'}'} ,\n {$sort: {totalValue: -1}'}',\n {$limit: 10}\n])