Con il framework di aggregazione, il risultato sarà leggermente diverso dall'output "desiderato" poiché invece di avere chiavi hash, otterrai un array di oggetti con _id
chiave con un valore che rappresenta il gruppo per campo. Ad esempio, invece di
{
"28-10-2016":{
"success_count": 10,
"failure_count": 10
},
"29-10-2016": {
"success_count": 10,
"failure_count": 10
}
}
avresti una struttura migliore come
[
{
"_id": "28-10-2016",
"success_count": 10,
"failure_count": 10
},
"_id": "29-10-2016",
"success_count": 10,
"failure_count": 10
}
]
Il raggiungimento del risultato di cui sopra richiederebbe l'utilizzo di $cond
operatore nel $sum
operatore accumulatore. Il $cond
l'operatore valuterà una condizione logica in base al suo primo argomento (se) e quindi restituisce il secondo argomento in cui la valutazione è vera (allora) o il terzo argomento in cui è falso (altrimenti). Questo converte la logica vero/falso in valori numerici 1 e 0 che alimentano $sum
rispettivamente:
"success_count": {
"$sum": {
"$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]
}
}
Come pipeline risultante, è necessario eseguire l'operazione di aggregazione che utilizza $dateToString
operatore nel _id
espressione chiave per $group
pipeline:
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);
})
Tuttavia, esiste un approccio più flessibile e con prestazioni migliori che viene eseguito molto più velocemente di quanto sopra, in cui la struttura dei dati più efficiente per il risultato dell'aggregazione segue lo schema, ad esempio:
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 }
]
}
]
Quindi considera l'esecuzione di una pipeline alternativa come segue
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);
})