Emanuel Salazar
Emanuel Salazar
El operador $count: {} no acepta ningún parámetro.
El resultado sería el mismo que el obtenido con { $sum: 1 }
Si trabajas con MongoDB Aggregation Framework y necesitas contar documentos o calcular promedios dentro de tus reportes, los operadores $count y $avg son tus aliados. Aquí aprendes a usarlos dentro de la etapa $group para enriquecer un pipeline que analiza propiedades de Airbnb por tipo, mostrando cuántas hay y cuál es su precio medio.
¿Por qué los operadores de acumulación viven dentro de $group?
MongoDB Aggregation Framework tiene más de 50 operadores, y al principio puede ser confuso saber cuál usar y cuándo. La regla práctica es esta: los operadores de acumulación se utilizan dentro de la etapa $group, porque su trabajo es manipular y procesar los datos que estás agrupando.
En este caso vas a sumar dos requisitos al reporte que ya tenías de la clase anterior:
¿Qué hace el operador $count en MongoDB? Cuenta los documentos que previamente agrupaste con
$group. Se suele implementar usando$sum: 1dentro de un campo nuevo.
¿Cómo cuento documentos con $sum dentro de $group?
Partes del pipeline que ya tenías en MongoDB Compass, donde el _id del $group es el tipo de propiedad. Para contar, creas un campo nuevo (por ejemplo, count) y le asignas el operador de acumulación $sum con el valor 1, lo que indica que sume una unidad por cada documento del grupo.
js { $group: { _id: "$property_type", count: { $sum: 1 } } }
Este campo todavía no aparece en el resultado final porque falta exponerlo en la etapa $project. Eso lo resolvemos al final.
¿Cómo calculo la media de precios con $avg?
Dentro del mismo $group agregas otro campo, llamémosle precioMedio, y usas el operador $avg indicando sobre qué campo quieres calcular el promedio. En tu caso, el campo price.
js { $group: { _id: "$property_type", count: { $sum: 1 }, precioMedio: { $avg: "$price" } } }
Recuerda que ambos operadores trabajan sobre los documentos agrupados, no sobre la colección completa. Por eso conviven dentro del mismo $group.
¿Cuál es la diferencia entre $sum y $avg?
$sumsuma valores (o cuenta si le pasas 1 fijo) y$avgcalcula el promedio aritmético del campo que le indiques dentro del grupo.
¿Cómo expongo count y average en la etapa $project?
La etapa $project es donde modelas el resultado final del reporte. Aquí tienes que mapear los campos calculados a nombres amigables, igual que ya hiciste con el precio mínimo y máximo en la clase anterior.
js { $project: { cantidadPropiedades: "$count", precioPromedioPropiedades: "$precioMedio" } }
Apenas guardas la etapa, MongoDB Compass refleja el resultado en el panel lateral: por cada tipo de propiedad ves cuántas existen y cuál es su precio promedio, junto al resto de campos que ya tenías.
¿Qué otros acumuladores puedes probar?
Una vez entiendes el patrón, puedes incluir más acumuladores dentro de $group según lo que pida tu reporte. Algunos muy usados en estadística y data mining:
$min para el valor mínimo de un campo.$max para el valor máximo.$sum para totales agregados.$avg para promedios.$count como etapa independiente cuando solo te interesa el conteo final.La colección de Airbnb tiene bastantes campos numéricos donde puedes practicar: número de habitaciones, número de camas, calificaciones de reseñas. Juega con ellos y observa cómo cambian los resultados.
¿Qué debes recordar al armar pipelines con acumuladores?
Hay tres ideas que te ahorran errores comunes cuando combinas $group y $project:
$count y $avg solo tienen sentido dentro de $group, porque operan sobre conjuntos agrupados.$group pero no lo declaras en $project, no aparecerá en el reporte final.$project (cantidadPropiedades, precioPromedioPropiedades) para que el resultado sea legible por quien consume el reporte.En las siguientes clases vas a trabajar con formatos y operadores sobre objetos más complejos como arrays, donde el potencial del Aggregation Framework se nota todavía más. ¿Con qué campo de Airbnb vas a probar primero, $avg o $sum? Cuéntame en los comentarios.
Mi solución:
use("sample_airbnb") db.listingsAndReviews.aggregate([ { $match: { "address.country_code": "US" } }, { $sort: { "property_type": 1, "price": 1 } }, { $group: { _id: "$property_type", less: { $first: { lessName: "$name", lessPrice: "$price", direction: "$address" } }, great: { $last: { greatName: "$name", greatPrice: "$price", direction: "$address", } }, q: { $count: {} }, avg: { $avg: "$price" } } }, { $project: { "_id": 0, "Tipo de propiedad": "$_id", "Menor precio": "$less.lessPrice", "Mayor precio": "$great.greatPrice", "Cantidad": "$q", "Media": { $round: "$avg" } } } ] )
Emanuel Salazar
Emanuel Salazar
El operador $count: {} no acepta ningún parámetro.
El resultado sería el mismo que el obtenido con { $sum: 1 }
Piero Nolte
Juan Bautista Pantigoso Cotrina
Mi query
[
{ $match: {
"address.country_code" : "US"
}},
{$sort: {
property_type: 1,
price: 1
}},
{ $group: {
_id: "$property_type",
count:{
$sum:1
},
precioMedia:{
$avg:"$price"
},
masBajo: {
$first: { // se obtiene el mas bajo
nombre: "$name",
precio: "$price",
direccion: "$address"
}
},
masAlto: {
$last: { // se obtiene el mas alto
nombre: "$name",
precio: "$price",
direccion: "$address"
},
},
},
},
{ $project :{
"_id":0,
"Tipo de propiedad":"$_id",
"Cantidad de propiedades":"$count",
"Precio promedio de propiedades":"$precioMedia",
"Menor precio":"$masBajo.precio",
"Mayor precio":"$masAlto.precio"
}}
]
En la explicación el profesor utilizó el operador de acumulación $sum en lugar del $count, aunque su comportamiento es equivalente su sintaxis es diferente:
{ $group: { _id: "$property_type", cantidad: { $count:{}}, economico: { $first: { nombre: "$name", precio: "$price", direccion: "$address" } }, costoso: { $last: { nombre: "$name", precio: "$price", direccion: "$address" } }, promedio: { $avg: "$price" } } }, { $project: { "Tipo de propiedad": "$_id", "Cantidad": "$cantidad", "El menor precio": "$economico.precio", "El mayor precio": "$costoso.precio", "El precio promedio": "$promedio", "_id": 0 } } ] ``` El operador `$count: {}` no acepta ningún parámetro.  El resultado sería el mismo que el obtenido con `{ $sum: 1 }`
Si utilizan VS Code con Mongo DB:
use('sample_airbnb') db.listingsAndReviews.aggregate( { $match: { "address.country": "United States" } }, { $group: { _id: "$property_type", countProperties: { $sum: 1 }, avgPrice: { $avg: "$price" }, MostExpensive: { $last: { name: "$name", price: "$price", address: "$address" } }, Cheapest: { $first: { name: "$name", price: "$price", address: "$address" } } } }, { $sort: { "_id": 1 } }, { $project: { "_id": 0, "Tipo de Propiedad": "$_id", "Menor precio": "$Cheapest.price", "Mayor precio": "$MostExpensive.price", "Opciones disponibles": "$countProperties", "Promedio de precios": { $round: ["$avgPrice", 2] } } } )