Skip to content

MongoDB 删除文档

MongoDB 提供了多种删除文档的方法,可以删除单个或多个文档。

删除单个文档

deleteOne() 方法

javascript
db.collection.deleteOne(filter, options)

基本示例

javascript
// 删除第一个匹配的文档
db.users.deleteOne({ name: "张三" })

返回结果

json
{
  "acknowledged": true,
  "deletedCount": 1
}

删除多个文档

deleteMany() 方法

javascript
db.collection.deleteMany(filter, options)

基本示例

javascript
// 删除所有匹配的文档
db.users.deleteMany({ status: "inactive" })

// 删除所有文档(清空集合)
db.users.deleteMany({})

删除条件

精确匹配删除

javascript
// 删除 name 为 "张三" 的文档
db.users.deleteOne({ name: "张三" })

// 删除多个条件匹配的文档
db.users.deleteMany({ status: "banned", createdAt: { $lt: new Date("2023-01-01") } })

使用操作符删除

javascript
// 删除年龄小于18的文档
db.users.deleteMany({ age: { $lt: 18 } })

// 删除特定状态的用户
db.users.deleteMany({ status: { $in: ["deleted", "banned"] } })

// 删除创建时间超过一年的文档
db.logs.deleteMany({
  createdAt: { $lt: new Date(Date.now() - 365 * 24 * 60 * 60 * 1000) }
})

查找并删除

findOneAndDelete() 方法

javascript
db.collection.findOneAndDelete(filter, options)

基本示例

javascript
// 查找并删除,返回被删除的文档
var deletedDoc = db.users.findOneAndDelete({ name: "张三" })
printjson(deletedDoc)

带排序的删除

javascript
// 删除最老的用户
db.users.findOneAndDelete(
  {},
  { sort: { createdAt: 1 } }
)

// 删除最新的用户
db.users.findOneAndDelete(
  {},
  { sort: { createdAt: -1 } }
)

投影返回字段

javascript
// 删除并返回指定字段
db.users.findOneAndDelete(
  { name: "张三" },
  { projection: { name: 1, email: 1 } }
)

删除选项

writeConcern

javascript
db.users.deleteOne(
  { name: "张三" },
  {
    writeConcern: {
      w: "majority",
      j: true,
      wtimeout: 5000
    }
  }
)

collation(排序规则)

javascript
db.users.deleteOne(
  { name: "zhangsan" },
  { collation: { locale: "zh", strength: 2 } }
)

批量删除

分批删除(大数据量)

javascript
// 分批删除,避免长时间锁定
var batchSize = 1000
var deleted = 0

while (true) {
  var result = db.oldlogs.deleteMany(
    { createdAt: { $lt: new Date("2023-01-01") } },
    { limit: batchSize }
  )
  
  deleted += result.deletedCount
  print("已删除:", deleted)
  
  if (result.deletedCount < batchSize) {
    break
  }
  
  // 短暂休眠,减轻数据库压力
  sleep(100)
}

print("总共删除:", deleted)

删除与删除集合对比

操作命令结果
删除所有文档deleteMany({})文档删除,集合保留
删除集合drop()集合和文档都删除
清空集合remove({})同 deleteMany
javascript
// 删除所有文档(保留集合和索引)
db.users.deleteMany({})

// 删除集合(删除所有内容和索引)
db.users.drop()

删除前确认

安全删除函数

javascript
function safeDelete(filter, collection) {
  collection = collection || "users"
  var col = db.getCollection(collection)
  
  // 统计要删除的文档数
  var count = col.countDocuments(filter)
  
  if (count === 0) {
    print("没有匹配的文档")
    return 0
  }
  
  print("将要删除", count, "条文档")
  print("查询条件:", JSON.stringify(filter))
  
  // 显示前5条预览
  print("预览前5条:")
  col.find(filter).limit(5).forEach(function(doc) {
    printjson(doc)
  })
  
  // 这里可以添加确认逻辑
  // 实际执行删除
  var result = col.deleteMany(filter)
  print("实际删除:", result.deletedCount, "条")
  
  return result.deletedCount
}

// 使用
safeDelete({ status: "inactive" }, "users")

软删除(推荐)

实现软删除

javascript
// 添加 deleted 标记,而不是真正删除
db.users.updateOne(
  { _id: ObjectId("...") },
  {
    $set: {
      deleted: true,
      deletedAt: new Date()
    }
  }
)

// 查询时过滤已删除
db.users.find({ deleted: { $ne: true } })

软删除优点

  • 数据可恢复
  • 保留历史记录
  • 满足审计要求

删除示例

定期清理任务

javascript
// 删除30天前的日志
db.appLogs.deleteMany({
  createdAt: {
    $lt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
  }
})

// 删除已注销超过90天的用户
db.users.deleteMany({
  status: "deleted",
  deletedAt: {
    $lt: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000)
  }
})

去重保留最新

javascript
// 删除重复数据,保留最新的
var duplicates = db.users.aggregate([
  { $group: { _id: "$email", count: { $sum: 1 }, ids: { $push: "$_id" } } },
  { $match: { count: { $gt: 1 } } }
])

duplicates.forEach(function(doc) {
  // 保留第一个(最新的),删除其他
  var idsToDelete = doc.ids.slice(1)
  db.users.deleteMany({ _id: { $in: idsToDelete } })
})

总结

删除文档要点:

  • deleteOne() 删除单个文档
  • deleteMany() 删除多个文档
  • findOneAndDelete() 查找并删除,可返回文档
  • 大批量删除建议分批进行
  • 考虑使用软删除保留数据

在下一章中,我们将学习 MongoDB 条件操作符