MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

grouper les données de collecte par plusieurs champs mongodb

Avec le framework d'agrégation, le résultat sera légèrement différent de votre sortie "souhaitée" car au lieu d'avoir des clés de hachage, vous obtenez un tableau d'objets avec le _id clé ayant une valeur qui représente votre groupe par champ. Par exemple, au lieu de

{
    "28-10-2016":{
        "success_count": 10, 
        "failure_count": 10
    },
    "29-10-2016": {
        "success_count": 10, 
        "failure_count": 10
    }
}

vous auriez une meilleure structure comme

[
    {
        "_id": "28-10-2016",
        "success_count": 10, 
        "failure_count": 10
    },
        "_id": "29-10-2016",
        "success_count": 10, 
        "failure_count": 10
    }
]

Pour obtenir le résultat ci-dessus, il faudrait utiliser le $cond opérateur dans $sum opérateur d'accumulateur. Le $cond L'opérateur évaluera une condition logique en fonction de son premier argument (if), puis retournera le deuxième argument où l'évaluation est vraie (then) ou le troisième argument où false (else). Cela convertit la logique vrai/faux en valeurs numériques 1 et 0 qui alimentent $sum respectivement :

"success_count": {
    "$sum": {
        "$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]
    }
}

En tant que pipeline résultant, il faut exécuter l'opération d'agrégation qui utilise le $dateToString opérateur dans le _id expression clé pour $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);
})

Cependant, il existe une approche plus flexible et plus performante qui s'exécute beaucoup plus rapidement que ci-dessus, où la structure de données la plus efficace pour votre résultat d'agrégation suit le schéma par exemple :

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 }
        ]
    }
]

Envisagez ensuite d'exécuter un pipeline alternatif comme suit

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