Con el marco de agregación, el resultado será ligeramente diferente de su salida "deseada" ya que en lugar de tener claves hash, obtiene una matriz de objetos con el _id
clave que tiene un valor que representa su grupo por campo. Por ejemplo, en lugar de
{
"28-10-2016":{
"success_count": 10,
"failure_count": 10
},
"29-10-2016": {
"success_count": 10,
"failure_count": 10
}
}
tendrías una mejor estructura como
[
{
"_id": "28-10-2016",
"success_count": 10,
"failure_count": 10
},
"_id": "29-10-2016",
"success_count": 10,
"failure_count": 10
}
]
Lograr el resultado anterior requeriría el uso de $cond
operador en el $sum
operador acumulador El $cond
El operador evaluará una condición lógica basada en su primer argumento (si) y luego devuelve el segundo argumento donde la evaluación es verdadera (entonces) o el tercer argumento donde es falso (else). Esto convierte la lógica verdadero/falso en valores numéricos 1 y 0 que se alimentan en $sum
respectivamente:
"success_count": {
"$sum": {
"$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]
}
}
Como canalización resultante, es necesario ejecutar la operación de agregación que utiliza $dateToString
operador en el _id
expresión clave para el $group
canalización:
Orders.aggregate([
{
"$group": {
"_id": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": "$created_at"
}
},
"success_count": {
"$sum": {
"$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]
}
},
"failure_count": {
"$sum": {
"$cond": [ { "$eq": [ "$status", "failure" ] }, 1, 0 ]
}
}
}
}
], function (err, orders){
if (err) throw err;
console.log(orders);
})
Sin embargo, existe un enfoque más flexible y de mejor rendimiento que se ejecuta mucho más rápido que el anterior, donde la estructura de datos más eficiente para el resultado de su agregación sigue el esquema, por ejemplo:
orders = [
{
"_id": "28-10-2016",
"counts": [
{ "status": "success", "count": 10 },
{ "status": "failure", "count": 10 }
]
},
{
"_id": "29-10-2016",
"counts": [
{ "status": "success", "count": 10 },
{ "status": "failure", "count": 10 }
]
}
]
Luego considere ejecutar una canalización alternativa de la siguiente manera
Orders.aggregate([
{
"$group": {
"_id": {
"date": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": "$created_at"
}
},
"status": { "$toLower": "$status" }
},
"count": { "$sum": 1 }
}
},
{
"$group": {
"_id": "$_id.date",
"counts": {
"$push": {
"status": "$_id.status",
"count": "$count"
}
}
}
}
], function (err, orders){
if (err) throw err;
console.log(orders);
})