MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

raggruppare i dati di raccolta per più campi mongodb

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);
})