MongoDB 如何创建 Time Series Collections(时间序列集合)

MongoDB 中,Time Series Collections(时间序列集合) 是一种专门用于高效存储和查询时间序列数据的集合类型。它从 MongoDB 5.0 开始引入,并在后续版本中持续优化。


📌 创建 Time Series Collection 的基本步骤

1. 确保 MongoDB 版本 ≥ 5.0

只有 MongoDB 5.0 及以上版本才支持时间序列集合。

2. 使用 createCollection() 命令创建

语法如下:

javascript 复制代码
db.createCollection("<collectionName>", {
  timeseries: {
    timeField: "<fieldThatStoresTheTimestamp>",
    metaField: "<optionalMetadataField>",
    granularity: "<seconds|minutes|hours>"
  }
})
参数说明:
  • timeField(必需):
    • 指定文档中表示时间戳的字段名。
    • 字段值必须是 Date 类型(BSON Date)。
  • metaField(可选):
    • 指定一个元数据字段,用于存储标签或分类信息(如设备 ID、传感器类型等)。
    • 元数据字段可以是任意 BSON 类型,但通常用作索引或分组依据。
  • granularity(可选,默认为 "seconds"):
    • 提示 MongoDB 数据写入的时间粒度,帮助优化内部存储结构。
    • 可选值:"seconds"、"minutes"、"hours"
    • 注意:这只是提示,不影响功能,但影响性能。
✅ 示例:创建一个传感器读数的时间序列集合
javascript 复制代码
db.createCollection("sensorData", {
  timeseries: {
    timeField: "timestamp",
    metaField: "sensorId",
    granularity: "minutes"
  }
})

然后你可以插入如下文档:

javascript 复制代码
db.sensorData.insertOne({
  timestamp: new Date(),
  sensorId: "temp-sensor-01",
  temperature: 23.5,
  humidity: 60
})

⚠️ 注意:你不能直接在时间序列集合上使用 update 或 delete 操作(MongoDB 6.3 之前完全不支持;6.3+ 开始有限支持)。因此,设计时应考虑是否需要修改历史数据。

3. (可选)为元数据字段创建索引

虽然时间序列集合会自动按时间排序,但如果你经常按 metaField 查询(比如按 sensorId),建议手动创建索引:

javascript 复制代码
db.sensorData.createIndex({ sensorId: 1 })

🔍 验证是否创建成功

你可以通过以下命令查看集合信息:

javascript 复制代码
db.sensorData.stats()

如果输出中包含 "type": "timeseries",说明创建成功。

📝 补充说明

时间序列集合底层使用列式存储优化,节省空间并提升聚合性能。

支持标准的聚合管道(如 group, bucketAuto 等),特别适合时间窗口分析。

从 MongoDB 7.0 开始,还支持二级时间序列集合(Secondary Time Series) 和更灵活的 schema。

✅ 关键点:Time Series Collection 必须在创建集合时显式声明

MongoDB 的 Time Series 功能 不是靠插入的数据结构自动识别的,而是必须在 create collection 命令中通过 timeseries 选项显式启用。否则,即使你字段叫 timestamp,它也只是个普通集合。

🔍 如何验证你是否真的创建了 Time Series Collection?
方法 1:使用 MongoDB Shell 检查

连接到数据库后执行:

javascript 复制代码
db.sensorData.stats()

如果返回结果中包含:

bash 复制代码
"timeseries": {
"timeField": "timestamp",
"metaField": "metadata",
"granularity": "seconds"
}

说明是真正的 Time Series Collection。如果是普通集合,不会有 timeseries 字段。

方法 2:通过 Java 驱动检查
java 复制代码
MongoDatabase db = mongoTemplate.getDb();
Document stats = db.runCommand(new Document("collStats", "sensorData"));
System.out.println(stats.toJson());

查看输出是否包含 "timeseries"

❌ 常见错误:你以为创建了,其实没创建

比如你写了:

java 复制代码
mongoTemplate.createCollection("sensorData"); // ❌ 这只是创建普通集合!

然后再去插入带 timestamp 的文档 ------ 这仍然是普通集合!

或者你在 @PostConstruct 中调用了 createTimeSeriesCollection(),但因为异常被吞掉、权限不足、集合已存在等原因,实际命令未生效。

🧪 实验对比(普通 vs 时间序列)

特性 普通集合 Time Series Collection
存储效率 一般 高(自动压缩、桶化)
写入性能 正常 更高(针对时间序列优化)
时间范围查询 需要索引 极快(内置时间排序
是否支持 update/delete单条 ❌(默认禁止)
自动过期(TTL) 需手动建 TTL 索引 支持 expireAfterSeconds
_id 字段 必须唯一 自动生成,不可设
💡 建议
  • 启动时严格校验:如上所示,检查集合是否存在且类型正确。
  • 不要依赖 Spring Data 自动创建:@Document 不会触发 Time Series 创建。
  • 开发阶段用 Shell 验证:db.collection.stats() 是最直接的方式。
如果你已经按上述方式创建,但 stats() 仍显示不是时间序列集合,请检查:
  • MongoDB 版本 ≥ 5.0?
  • 用户是否有 createCollection 权限?
  • 集合是否早已存在(且是普通集合)?→ 需先删除再重建(⚠️ 生产环境谨慎!)