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

Resultado del grupo por intervalo de tiempo de 15 minutos en MongoDb

Hay un par de maneras de hacer esto.

El primero es con operadores de agregación de fechas, que le permiten diseccionar los valores de "fecha" en los documentos. Específicamente para "agrupar" como intención 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 }
  }}
])

La segunda forma es usando un pequeño truco de cuando se resta un objeto de fecha (u otra operación matemática directa) de otro objeto de fecha, entonces el resultado es un valor numérico que representa la marca de tiempo de época en milisegundos entre los dos objetos. Entonces, solo usando la fecha de la época, obtienes la representación de la época en milisegundos. Luego use matemáticas de fecha para el 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 }
    }}
])

Por lo tanto, depende del tipo de formato de salida que desee para el intervalo de agrupación. Ambos representan básicamente lo mismo y tienen suficientes datos para reconstruir como un objeto de "fecha" en su código.

Puede poner cualquier otra cosa que desee en la parte del "operador de agrupación" después de la agrupación _id . Solo estoy usando el ejemplo básico de "recuento" en lugar de cualquier declaración real de usted mismo sobre lo que realmente quiere hacer.

MongoDB 4.x y superior

Hubo algunas adiciones a los operadores de agregación de fechas desde la escritura original, pero a partir de MongoDB 4.0 habrá una "fundición real de tipos" en lugar de los trucos matemáticos básicos que se hacen aquí con la conversión de fechas BSON.

Por ejemplo, podemos usar $toLong y $toDate como nuevos ayudantes aquí:

db.collection.aggregate([
  { "$group": {
    "_id": {
      "$toDate": {
        "$subtract": [
          { "$toLong": "$created_at" },
          { "$mod": [ { "$toLong": "$created_at" }, 1000 * 60 * 15 ] }
        ]
      }
    },
    "count": { "$sum": 1 }
  }}
])

Eso es un poco más corto y no requiere definir una fecha BSON externa para el valor de "época" como una constante en la definición de la canalización, por lo que es bastante consistente para todas las implementaciones de lenguaje.

Esos son solo dos de los métodos de "ayuda" para la conversión de tipos que se relacionan con $convert método, que es una forma "más larga" de la implementación que permite un manejo personalizado en null o error en la conversión.

Incluso es posible con dicha conversión obtener la Date información del ObjectId de la clave principal, ya que sería una fuente confiable de la fecha de "creación":

db.collection.aggregate([
  { "$group": {
    "_id": {
      "$toDate": {
        "$subtract": [
          { "$toLong": { "$toDate": "$_id" }  },
          { "$mod": [ { "$toLong": { "$toDate": "$_id" } }, 1000 * 60 * 15 ] }
        ]
      }
    },
    "count": { "$sum": 1 }
  }}
])

Por lo tanto, la "transmisión de tipos" con este tipo de conversión puede ser una herramienta bastante poderosa.

Advertencia - ObjectId los valores están limitados a la precisión al segundo solo para el valor de tiempo interno que forma parte de sus datos, lo que permite que $toDate conversión. El "tiempo" insertado real probablemente depende del controlador en uso. Donde precisión es obligatorio, todavía se recomienda usar un campo de fecha BSON discreto en lugar de confiar en ObjectId valores.