MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Agrupar por intervalos de data


Existem operadores de agregação de data disponíveis para a estrutura de agregação do MongoDB. Por exemplo, um $dayOfYear operador é usado para obter esse valor a partir da data para uso no agrupamento:
db.collection.aggregate([
    { "$group": {
        "_id": { "$dayOfYear": "$datetime" },
        "total": { "$sum": "$count" }
    }}
])

Ou você pode usar uma abordagem matemática de datas. Ao aplicar a data de época, você converte o objeto de data em um número onde a matemática pode ser aplicada:
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" }
    }}
])

Se o que você procura são intervalos de um ponto no tempo atual, o que você deseja é basicamente a abordagem matemática de datas e trabalhar em algumas condicionais por meio do $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
                ]
            }
        }
    }}
])

É essencialmente a mesma abordagem do exemplo SQL, em que a consulta avalia condicionalmente se o valor de data está dentro do intervalo necessário e decide se deve ou não adicionar o valor à soma.

A única adição aqui é o $match adicional estágio para restringir a consulta para atuar apenas nos itens que possivelmente estariam dentro do intervalo máximo de um ano que você está solicitando. Isso o torna um pouco melhor do que o SQL apresentado, pois um índice pode ser usado para filtrar esses valores e você não precisa "forçar bruta" por meio de dados não correspondentes na coleção.

Sempre é uma boa ideia restringir a entrada com $match ao usar um pipeline de agregação.