Volver a MongoDB Intermedio
Colecciones de Series Temporales en MongoDB
Crear una Colección Time Series
db.createCollection("datosSensores", {
timeseries: {
timeField: "timestamp", // obligatorio: campo ISODate
metaField: "sensorId", // opcional: identifica la fuente
granularity: "seconds" // seconds | minutes | hours
},
expireAfterSeconds: 86400 * 90 // eliminar automáticamente a los 90 días
})
Insertar Datos
// Insertar una lectura
await db.collection("datosSensores").insertOne({
timestamp: new Date(),
sensorId: "sensor-001",
ubicacion: "almacen-A",
lecturas: {
temperatura: 22.5,
humedad: 65.3,
presion: 1013.25
}
})
// Inserción masiva eficiente
const lecturas = Array.from({ length: 1000 }, (_, i) => ({
timestamp: new Date(Date.now() - i * 1000),
sensorId: "sensor-001",
lecturas: { temperatura: 20 + Math.random() * 5 }
}))
await db.collection("datosSensores").insertMany(lecturas)
Consultar Series Temporales
// Consulta por rango (usa agrupación temporal interna)
db.datosSensores.find({
sensorId: "sensor-001",
timestamp: {
$gte: new Date("2024-01-01"),
$lt: new Date("2024-02-01")
}
})
// Agregación con cubos temporales (promedio por hora)
db.datosSensores.aggregate([
{
$match: {
sensorId: "sensor-001",
timestamp: { $gte: new Date("2024-01-01") }
}
},
{
$group: {
_id: { $dateTrunc: { date: "$timestamp", unit: "hour" } },
tempPromedio: { $avg: "$lecturas.temperatura" },
tempMaxima: { $max: "$lecturas.temperatura" },
tempMinima: { $min: "$lecturas.temperatura" }
}
},
{ $sort: { _id: 1 } }
])
$setWindowFields: Medias Móviles
db.datosSensores.aggregate([
{ $match: { sensorId: "sensor-001" } },
{ $sort: { timestamp: 1 } },
{
$setWindowFields: {
partitionBy: "$sensorId",
sortBy: { timestamp: 1 },
output: {
mediaMovil5min: {
$avg: "$lecturas.temperatura",
window: {
range: [-5, 0],
unit: "minute"
}
},
totalAcumulado: {
$sum: "$lecturas.temperatura",
window: { documents: ["unbounded", "current"] }
}
}
}
}
])
Buenas Prácticas
// 1. Filtrar siempre por metaField y rango temporal primero
db.datosSensores.find({
sensorId: "sensor-001", // metaField (indexado)
timestamp: { $gte: inicio } // timeField (agrupado)
})
// 2. Elegir granularity según la frecuencia de muestreo
// - "seconds": datos cada pocos segundos
// - "minutes": datos cada pocos minutos
// - "hours": datos cada pocas horas
// 3. Configurar TTL para gestionar almacenamiento
db.createCollection("metricas", {
timeseries: { timeField: "ts", metaField: "host" },
expireAfterSeconds: 86400 * 30 // 30 días
})