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

Agrupe o resultado por intervalo de tempo de 15 minutos no MongoDb


Há algumas maneiras de fazer isso.

A primeira é com os operadores de agregação de datas, que permitem dissecar os valores de "data" em documentos. Especificamente para "agrupar" como a intenção principal:
db.collection.aggregate([
  { "$group": {
    "_id": {
      "year": { "$year": "$created_at" },
      "dayOfYear": { "$dayOfYear": "$created_at" },
      "hour": { "$hour": "$created_at" },
      "interval": {
        "$subtract": [ 
          { "$minute": "$created_at" },
          { "$mod": [{ "$minute": "$created_at"}, 15] }
        ]
      }
    }},
    "count": { "$sum": 1 }
  }}
])

A segunda maneira é usar um pequeno truque de quando um objeto de data é subtraído (ou outra operação matemática direta) de outro objeto de data, então o resultado é um valor numérico que representa os milissegundos do timestamp da época entre os dois objetos. Então, apenas usando a data de época, você obtém a representação de milissegundos de época. Em seguida, use a matemática da data para o intervalo:
db.collection.aggregate([
    { "$group": {
        "_id": {
            "$subtract": [
                { "$subtract": [ "$created_at", new Date("1970-01-01") ] },
                { "$mod": [ 
                    { "$subtract": [ "$created_at", new Date("1970-01-01") ] },
                    1000 * 60 * 15
                ]}
            ]
        },
        "count": { "$sum": 1 }
    }}
])

Portanto, depende de que tipo de formato de saída você deseja para o intervalo de agrupamento. Ambos representam basicamente a mesma coisa e possuem dados suficientes para serem reconstruídos como um objeto "data" em seu código.

Você pode colocar o que quiser na parte "operador de agrupamento" após o agrupamento _id . Estou apenas usando o exemplo básico de "contagem" em vez de qualquer declaração real de você mesmo sobre o que você realmente quer fazer.

MongoDB 4.xe superior


Houve algumas adições aos operadores de agregação de datas desde a escrita original, mas a partir do MongoDB 4.0 haverá uma "conversão real de tipos" em oposição aos truques matemáticos básicos feitos aqui com a conversão de data BSON.

Por exemplo, podemos usar $toLong e $toDate como novos ajudantes aqui:
db.collection.aggregate([
  { "$group": {
    "_id": {
      "$toDate": {
        "$subtract": [
          { "$toLong": "$created_at" },
          { "$mod": [ { "$toLong": "$created_at" }, 1000 * 60 * 15 ] }
        ]
      }
    },
    "count": { "$sum": 1 }
  }}
])

Isso é um pouco mais curto e não requer a definição de uma data BSON externa para o valor "epoch" como uma constante na definição do pipeline, por isso é bastante consistente para todas as implementações de linguagem.

Esses são apenas dois dos métodos "auxiliares" para conversão de tipo, todos vinculados ao $convert método, que é uma forma "mais longa" da implementação que permite manipulação personalizada em null ou erro na conversão.

É até possível com essa transmissão obter a Date informações do ObjectId da chave primária, pois esta seria uma fonte confiável de data de "criação":
db.collection.aggregate([
  { "$group": {
    "_id": {
      "$toDate": {
        "$subtract": [
          { "$toLong": { "$toDate": "$_id" }  },
          { "$mod": [ { "$toLong": { "$toDate": "$_id" } }, 1000 * 60 * 15 ] }
        ]
      }
    },
    "count": { "$sum": 1 }
  }}
])

Portanto, "tipos de elenco" com esse tipo de conversão podem ser uma ferramenta bastante poderosa.

Aviso - ObjectId os valores são limitados à precisão ao segundo apenas para o valor de tempo interno que compõe parte de seus dados, permitindo que o $toDate conversão. O "tempo" real inserido provavelmente depende do driver em uso. Onde precisão for obrigatório, ainda é recomendável usar um campo BSON Date discreto em vez de confiar em ObjectId valores.