Agregaciones y Procesamiento de Datos
1. ¿Qué es una agregación? #
Las consultas normales (find()) nos permiten buscar datos, pero las agregaciones permiten hacer análisis avanzado, como contar registros, calcular promedios, sumar valores, etc.
📌 Ejemplo:
Queremos saber el precio promedio de todos los productos en nuestra base de datos.
✔️ Con una consulta normal (find()), obtenemos todos los productos:
1db.productos.find()
✔️ Con una agregación, podemos calcular el precio promedio:
1db.productos.aggregate([ 2 { $group: { _id: null, precioPromedio: { $avg: "$precio" } } } 3])
✅ Resultado:
1[ 2 { "precioPromedio": 950 } 3]
Conclusión: La agregación nos devuelve información procesada sin necesidad de trabajar los datos fuera de la base.
2. El Pipeline de Agregación #
Una agregación en MongoDB se compone de varias etapas (como una tubería que procesa datos paso a paso).
📌 Las etapas más usadas:
| Etapa | ¿Para qué sirve? |
|---|---|
$match | Filtrar documentos (como un WHERE en SQL) |
$group | Agrupar documentos y calcular valores (sumas, promedios, conteos, etc.) |
$project | Seleccionar qué campos mostrar o transformar datos |
$sort | Ordenar los resultados |
$limit | Limitar la cantidad de resultados |
$lookup | Unir datos de otra colección (similar a un JOIN en SQL) |
3. Ejemplo Práctico: Análisis de Productos #
Imaginemos que tenemos una colección de productos con esta estructura:
1[ 2 { "nombre": "Laptop", "marca": "Dell", "precio": 1200, "stock": 5 }, 3 { "nombre": "Celular", "marca": "Samsung", "precio": 800, "stock": 10 }, 4 { "nombre": "Tablet", "marca": "Apple", "precio": 1000, "stock": 3 } 5]
🔹 Filtrar productos con $match #
Queremos ver solo los productos con precio mayor a 900:
1db.productos.aggregate([ 2 { $match: { precio: { $gt: 900 } } } 3])
✅ Resultado:
1[ 2 { "nombre": "Laptop", "marca": "Dell", "precio": 1200 }, 3 { "nombre": "Tablet", "marca": "Apple", "precio": 1000 } 4]
🔹 Agrupar productos por marca con $group #
Queremos saber cuántos productos hay de cada marca:
1db.productos.aggregate([ 2 { $group: { _id: "$marca", cantidad: { $sum: 1 } } } 3])
✅ Resultado:
1[ 2 { "_id": "Dell", "cantidad": 1 }, 3 { "_id": "Samsung", "cantidad": 1 }, 4 { "_id": "Apple", "cantidad": 1 } 5]
🔹 Calcular el precio promedio de los productos con $group #
1db.productos.aggregate([ 2 { $group: { _id: null, precioPromedio: { $avg: "$precio" } } } 3])
✅ Resultado:
1[ 2 { "precioPromedio": 1000 } 3]
🔹 Seleccionar solo algunos campos con $project #
Si solo queremos ver el nombre y el precio de los productos:
1db.productos.aggregate([ 2 { $project: { _id: 0, nombre: 1, precio: 1 } } 3])
✅ Resultado:
1[ 2 { "nombre": "Laptop", "precio": 1200 }, 3 { "nombre": "Celular", "precio": 800 }, 4 { "nombre": "Tablet", "precio": 1000 } 5]
🔹 Ordenar productos por precio con $sort #
Para mostrar los productos del más barato al más caro:
1db.productos.aggregate([ 2 { $sort: { precio: 1 } } 3])
✅ Resultado:
1[ 2 { "nombre": "Celular", "precio": 800 }, 3 { "nombre": "Tablet", "precio": 1000 }, 4 { "nombre": "Laptop", "precio": 1200 } 5]
🔹 Limitar la cantidad de resultados con $limit #
Si solo queremos ver los 2 productos más baratos:
1db.productos.aggregate([ 2 { $sort: { precio: 1 } }, 3 { $limit: 2 } 4])
✅ Resultado:
1[ 2 { "nombre": "Celular", "precio": 800 }, 3 { "nombre": "Tablet", "precio": 1000 } 4]
🔹 Unir información con $lookup (JOIN en NoSQL) #
Si tenemos una colección de pedidos y queremos ver los detalles del producto en cada pedido, usamos $lookup.
Ejemplo: Colección pedidos #
1[ 2 { "_id": 1, "producto_id": "Laptop", "cantidad": 2 }, 3 { "_id": 2, "producto_id": "Celular", "cantidad": 1 } 4]
Consulta para unir pedidos con productos #
1db.pedidos.aggregate([ 2 { 3 $lookup: { 4 from: "productos", 5 localField: "producto_id", 6 foreignField: "nombre", 7 as: "productoDetalles" 8 } 9 } 10])
✅ Resultado:
1[ 2 { "_id": 1, "producto_id": "Laptop", "cantidad": 2, "productoDetalles": [{ "marca": "Dell", "precio": 1200 }] }, 3 { "_id": 2, "producto_id": "Celular", "cantidad": 1, "productoDetalles": [{ "marca": "Samsung", "precio": 800 }] } 4]
📌 Así podemos hacer un "JOIN" en bases documentales.
4. ¿Por qué usar agregaciones? #
✅ Permiten procesar grandes volúmenes de datos sin necesidad de traer todo al código
✅ Mejoran el rendimiento y evitan consultas innecesarias
✅ Facilitan el análisis de datos directamente en la base de datos