Bueno, no puedes simplemente "hacer las paces". operadores como $mode
no es un operador de agregación, y las únicas cosas que puede usar son aquellas que existen realmente
.
Entonces, para devolver el valor de la categoría dentro del período de tiempo agrupado que ocurre más, es necesario agrupar primero en cada uno de esos valores y devolver el recuento de ocurrencias. Luego puede ordenar estos resultados por ese conteo y devolver el valor de categoría que registró el conteo más alto dentro de ese período:
// Filter dates
{ "$match": {
"dt": {
"$gt": new Date("October 13, 2010 12:00:00"),
"$lt": new Date("November 13, 2010 12:00:00")
}
}},
// Group by hour and category, with avg and count
{ "$group": {
"_id": {
"dt": {
"$add": [
{
"$subtract": [
{ "$subtract": ["$dt", new Date(0)] },
{
"$mod": [
{ "$subtract": ["$dt", new Date(0)] },
3600000//1000 * 60 * 60
]
}
]
},
new Date(0)
]
},
"category": "$category"
},
"price": { "$avg": "$price" },
"count": { "$sum": 1 }
}},
// Sort on date and count
{ "$sort": { "_id.dt": 1, "count": -1 }},
// Group on just the date, keeping the avg and the first category
{ "$group": {
"_id": "$_id.dt",
"price": { "$avg": "$price"}
"category": { "$first": "$_id.category" }
}}
Entonces $group
tanto en la fecha como en la categoría y conservar el recuento de categorías a través de $sum
. Entonces usted $sort
por lo tanto, el "recuento" más grande está arriba para cada fecha agrupada. Y finalmente use $first
cuando aplica otro $group
eso solo se aplica a la fecha en sí, para devolver esa categoría con el recuento más grande para cada fecha.
No se deje tentar por operadores como $max
ya que no trabajan aquí. La diferencia clave es la relación "vinculada" con el "registro/documento" producido para cada valor de categoría. Por lo tanto, no es el "recuento" máximo lo que desea o el valor máximo de "categoría", sino el valor de categoría que "produjo" el recuento más grande. Por lo tanto, hay un $sort
necesario aquí.
Finalmente, algunos hábitos que "deberías" romper:
-
No utilice datos de instancia de fecha en formato no UTC como entrada a menos que realmente sepa lo que está haciendo. Las fechas siempre se convertirán a UTC, por lo que al menos en las listas de prueba, debe acostumbrarse a especificar el valor de la fecha de esa manera.
-
Podría verse un poco más limpio de otra manera, pero cosas como
1000 * 60 * 60
son un código mucho más descriptivo de lo que está haciendo que3600000
. Mismo valor, pero una forma es indicativa de sus unidades de tiempo de un vistazo. -
Compuesto
_id
cuando solo hay un valor único también puede confundir los problemas. Así que no tiene mucho sentido acceder a_id.dt
si ese fuera el único valor presente. Cuando hay más de una sola propiedad dentro de_id
entonces esta bien Pero los valores individuales deben asignarse directamente a_id
solo. Nada ganado de otra manera, y solo es bastante claro.