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

Regrouper par intervalles de dates

Il existe des opérateurs d'agrégation de date disponibles pour le cadre d'agrégation de MongoDB. Ainsi, par exemple, un $dayOfYear est utilisé pour obtenir cette valeur à partir de la date à utiliser dans le regroupement :

db.collection.aggregate([
    { "$group": {
        "_id": { "$dayOfYear": "$datetime" },
        "total": { "$sum": "$count" }
    }}
])

Ou vous pouvez utiliser une approche mathématique de date à la place. En appliquant la date d'époque, vous convertissez l'objet date en un nombre où les calculs peuvent être appliqués :

db.collection.aggregate([
    { "$group": {
        "_id": { 
            "$subtract": [
                { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                { "$mod": [
                    { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                    1000 * 60 * 60 * 24
                ]}
            ]
        },
        "total": { "$sum": "$count" }
    }}
])

Si ce que vous recherchez, ce sont des intervalles à partir d'un point actuel dans le temps, alors ce que vous voulez, c'est essentiellement l'approche mathématique de la date et travailler dans certaines conditions via le $cond opérateur :

db.collection.aggregate([
    { "$match": {
        "datetime": { 
            "$gte": new Date(new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 365 ))
        }
    }},
    { "$group": {
        "_id": null,
        "24hours": { 
            "$sum": {
                "$cond": [
                    { "$gt": [
                        { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                        new Date().valueOf() - ( 1000 * 60 * 60 * 24 )
                    ]},
                    "$count",
                    0
                ]
            }
        },
        "30days": { 
            "$sum": {
                "$cond": [
                    { "$gt": [
                        { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                        new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 30 )
                    ]},
                    "$count",
                    0
                ]
            }
        },
        "OneYear": { 
            "$sum": {
                "$cond": [
                    { "$gt": [
                        { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                        new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 365 )
                    ]},
                    "$count",
                    0
                ]
            }
        }
    }}
])

C'est essentiellement la même approche que l'exemple SQL, où la requête évalue de manière conditionnelle si la valeur de date se situe dans la plage requise et décide d'ajouter ou non la valeur à la somme.

Le seul ajout ici est le $match supplémentaire étape pour limiter la requête afin qu'elle n'agisse que sur les éléments susceptibles de se situer dans la plage maximale d'un an que vous demandez. Cela le rend un peu meilleur que le SQL présenté dans la mesure où un index peut être utilisé pour filtrer ces valeurs et vous n'avez pas besoin de "force brute" à travers des données non correspondantes dans la collection.

Toujours une bonne idée de restreindre l'entrée avec $match lors de l'utilisation d'un pipeline d'agrégation.