在 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 权限?
- 集合是否早已存在(且是普通集合)?→ 需先删除再重建(⚠️ 生产环境谨慎!)