Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MongoDB

MongoDB 限制集合文档数量:使用 Capped Collection

本文介绍 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+)