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

Agréger $group pour plusieurs plages de dates

Vous devez déterminer conditionnellement la clé de regroupement en fonction de l'endroit où la date actuelle se situe entre la plage. Ceci est essentiellement réalisé via $cond avec des conditions imbriquées et la variante logique de $lt :

// work out dates somehow
var today = new Date(),
    oneDay = ( 1000 * 60 * 60 * 24 ),
    thirtyDays = new Date( today.valueOf() - ( 30 * oneDay ) ),
    fifteenDays = new Date( today.valueOf() - ( 15 * oneDay ) ),
    sevenDays = new Date( today.valueOf() - ( 7 * oneDay ) );

db.collection.aggregate([
    { "$match": {
        "date": { "$gte": thirtyDays }
    }},
    { "$group": {
        "_id": {
            "$cond": [
                { "$lt": [ "$date", fifteenDays ] },
                "16-30",
                { "$cond": [
                    { "$lt": [ "$date", sevenDays ] },
                    "08-15",
                    "01-07"
                ]}
            ]
        },
        "count": { "$sum": 1 },
        "totalValue": { "$sum": "$value" }
    }}
])

Comme $cond est un opérateur ternaire, la première condition est évaluée pour voir si la condition est vraie, et quand vrai le deuxième argument est retourné sinon le troisième est retourné quand faux. Donc en imbriquant un autre $cond dans le cas faux, vous obtenez le test logique sur l'endroit où la date tombe, soit "moins que la date de 15 jours" ce qui signifie que c'est dans la plage la plus ancienne, ou "moins de 7 jours" ce qui signifie la plage moyenne, ou bien sûr c'est dans la nouvelle gamme.

Je préfixe juste les nombres ici moins de 10 avec un 0 cela vous donne donc quelque chose à trier si vous le souhaitez, puisque la sortie de "keys" dans $group n'est pas ordonné en soi.

Mais c'est ainsi que vous procédez en une seule requête. Vous déterminez simplement ce que la clé de regroupement doit être en fonction de l'emplacement de la date et vous cumulez pour chaque clé.