本文介绍 MongoDB Capped Collection (固定大小集合) 特性,通过创建时指定 capped: true、size (字节上限) 和 max (文档数上限) 来自动限制集合存储的文档数量,旧文档会被自动覆盖 (FIFO)。
创建 Capped Collection 语法
db.createCollection("yourCollectionName", {
capped: true,
size: yourSizeInBytes, // 最大存储字节数 (含索引)
max: howManyRecordsYouWant // 最大文档数量 (可选)
})
创建示例:限制 3 个文档,200KB
> db.createCollection("limitTheNumberOfRecordsDemo", {capped:true, size:200024, max:3})
{ "ok" : 1 }
插入 6 个文档 (超过 max=3)
> db.limitTheNumberOfRecordsDemo.insertOne({"ClientName":"James Brown"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9e601b50a6c6dd317adad") }
> db.limitTheNumberOfRecordsDemo.insertOne({"ClientName":"Sam Williams"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9e60bb50a6c6dd317adae") }
> db.limitTheNumberOfRecordsDemo.insertOne({"ClientName":"David Miller"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9e612b50a6c6dd317adaf") }
> db.limitTheNumberOfRecordsDemo.insertOne({"ClientName":"Carol Taylor"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9e61ab50a6c6dd317adb0") }
> db.limitTheNumberOfRecordsDemo.insertOne({"ClientName":"Adam Smith"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9e649b50a6c6dd317adb1") }
> db.limitTheNumberOfRecordsDemo.insertOne({"ClientName":"John Doe"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9e64fb50a6c6dd317adb2") }
查询结果:仅保留最后 3 个 (FIFO 自动淘汰)
> db.limitTheNumberOfRecordsDemo.find();
{ "_id" : ObjectId("5cd9e61ab50a6c6dd317adb0"), "ClientName" : "Carol Taylor" }
{ "_id" : ObjectId("5cd9e649b50a6c6dd317adb1"), "ClientName" : "Adam Smith" }
{ "_id" : ObjectId("5cd9e64fb50a6c6dd317adb2"), "ClientName" : "John Doe" }
Capped Collection 核心特性
| 特性 | 说明 |
|---|---|
| 固定大小 | 达到 size 字节上限时自动覆盖最旧文档 |
| 文档数上限 | 可选 max 参数限制文档数量,先到先得 |
| 插入顺序 = 存储顺序 | 天然有序,无需索引即可按插入序遍历 |
| 高性能写入 | 无需维护复杂索引,适合日志、缓存、队列 |
| 不支持删除单个文档 | 只能 drop 整个集合或待覆盖 |
| 不支持更新导致文档变大 | 更新后大小不能超过原大小 |
| _id 索引自动创建 | 但可选择不创建 (_id index 可选) |
查看集合是否为 Capped
> db.limitTheNumberOfRecordsDemo.stats().capped true > db.limitTheNumberOfRecordsDemo.stats().max 3
转换普通集合为 Capped (不可逆)
// 必须先备份数据,再重建
db.createCollection("newCapped", {capped: true, size: 1000000, max: 10000});
db.oldCollection.find().forEach(d => db.newCapped.insert(d));
db.oldCollection.drop();
db.newCapped.renameCollection("oldCollection");
典型应用场景
- 日志存储 (保留最近 N 条/最近 N 天)
- 消息队列 / 事件溯源
- 临时缓存 / 会话存储
- 审计追踪 (固定保留窗口)
- 物联网传感器数据滚动窗口
注意事项
size包含数据 + 索引开销,预留充足空间- 无法手动删除单条,只能等自然淘汰或 drop 重建
- 分片集群中不支持 Capped Collection
- 事务中不可写入 Capped Collection (MongoDB 4.2+)