sql >> Base de Datos >  >> NoSQL >> MongoDB

Agrupar por intervalos de fechas

Hay operadores de agregación de fechas disponibles para el marco de agregación de MongoDB. Entonces, por ejemplo, un $dayOfYear El operador se usa para obtener ese valor de la fecha para usar en la agrupación:

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

O puede usar un enfoque matemático de fecha en su lugar. Al aplicar la fecha de época, convierte el objeto de fecha en un número donde se pueden aplicar las matemáticas:

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 lo que busca son intervalos desde un punto actual en el tiempo, entonces lo que quiere es básicamente el enfoque matemático de fecha y trabajar en algunos condicionales a través de $cond operador:

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

Es esencialmente el mismo enfoque que el ejemplo de SQL, donde la consulta evalúa condicionalmente si el valor de la fecha se encuentra dentro del rango requerido y decide si agregar o no el valor a la suma.

La única adición aquí es el $match adicional etapa para restringir la consulta para que solo actúe en aquellos elementos que posiblemente estarían dentro del rango máximo de un año que está solicitando. Eso lo hace un poco mejor que el SQL presentado en el sentido de que se podría usar un índice para filtrar esos valores y no es necesario "fuerza bruta" a través de datos que no coinciden en la colección.

Siempre es una buena idea restringir la entrada con $match cuando se usa una canalización de agregación.