MongoDB文档删除 #

一、删除概述 #

1.1 删除方法 #

MongoDB提供两种删除方式:

方法 说明
deleteOne 删除单个文档
deleteMany 删除多个文档

1.2 删除注意事项 #

注意事项 说明
不可恢复 删除操作不可逆,建议先备份
索引保留 删除文档不会删除索引
固定集合 固定集合不能删除单个文档

二、deleteOne方法 #

2.1 基本删除 #

javascript
// 删除单个文档
db.users.deleteOne({ name: "John" })

// 输出
{
    "acknowledged": true,
    "deletedCount": 1
}

2.2 条件删除 #

javascript
// 按条件删除
db.users.deleteOne({ _id: ObjectId("507f1f77bcf86cd799439011") })

// 删除第一个匹配的文档
db.users.deleteOne({ status: "inactive" })

2.3 删除选项 #

javascript
// 删除选项
db.users.deleteOne(
    { name: "John" },
    {
        writeConcern: { w: "majority", j: true },
        collation: { locale: "en", strength: 2 }
    }
)

三、deleteMany方法 #

3.1 批量删除 #

javascript
// 删除多个文档
db.users.deleteMany({ status: "inactive" })

// 输出
{
    "acknowledged": true,
    "deletedCount": 10
}

3.2 条件删除 #

javascript
// 删除所有匹配文档
db.users.deleteMany({ age: { $lt: 18 } })

// 复杂条件删除
db.orders.deleteMany({
    status: "cancelled",
    createdAt: { $lt: new Date("2024-01-01") }
})

// 删除所有文档
db.users.deleteMany({})

3.3 删除选项 #

javascript
// 删除选项
db.users.deleteMany(
    { status: "inactive" },
    {
        writeConcern: { w: "majority" },
        collation: { locale: "en", strength: 2 }
    }
)

四、findOneAndDelete #

4.1 查找并删除 #

javascript
// 查找并删除
db.users.findOneAndDelete(
    { name: "John" },
    {
        projection: { name: 1, email: 1 },
        sort: { age: -1 },
        maxTimeMS: 5000
    }
)

// 输出:返回被删除的文档
{
    "_id": ObjectId("..."),
    "name": "John",
    "email": "john@example.com"
}

4.2 使用场景 #

javascript
// 获取并删除队列中的任务
db.tasks.findOneAndDelete(
    { status: "pending" },
    { sort: { priority: -1, createdAt: 1 } }
)

// 获取并删除最旧的日志
db.logs.findOneAndDelete(
    {},
    { sort: { timestamp: 1 } }
)

五、remove方法(已废弃) #

5.1 基本用法 #

javascript
// remove方法(已废弃,不推荐使用)
db.users.remove({ name: "John" })

// 删除单个文档
db.users.remove({ name: "John" }, true)

注意: remove方法已废弃,推荐使用deleteOne和deleteMany。

六、批量删除 #

6.1 bulkWrite删除 #

javascript
// 批量删除操作
db.users.bulkWrite([
    {
        deleteOne: {
            filter: { name: "John" }
        }
    },
    {
        deleteMany: {
            filter: { status: "inactive" }
        }
    }
])

// 输出
{
    "acknowledged": true,
    "deletedCount": 11
}

6.2 分批删除 #

javascript
// 分批删除大量数据
while (true) {
    const result = db.logs.deleteMany(
        { timestamp: { $lt: new Date("2024-01-01") } },
        { limit: 1000 }
    )
    print(`Deleted ${result.deletedCount} documents`)
    if (result.deletedCount === 0) break
}

七、删除策略 #

7.1 软删除 #

javascript
// 软删除:标记为已删除
db.users.updateOne(
    { _id: ObjectId("...") },
    {
        $set: {
            deleted: true,
            deletedAt: new Date()
        }
    }
)

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

// 定期清理已删除文档
db.users.deleteMany({
    deleted: true,
    deletedAt: { $lt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) }
})

7.2 TTL索引自动删除 #

javascript
// 创建TTL索引自动删除过期文档
db.logs.createIndex(
    { createdAt: 1 },
    { expireAfterSeconds: 3600 }  // 1小时后删除
)

// 修改TTL时间
db.runCommand({
    collMod: "logs",
    index: {
        keyPattern: { createdAt: 1 },
        expireAfterSeconds: 7200  // 改为2小时
    }
})

7.3 固定集合自动删除 #

javascript
// 固定集合自动删除最旧文档
db.createCollection("logs", {
    capped: true,
    size: 10485760,  // 10MB
    max: 10000       // 最多10000个文档
})

八、删除性能 #

8.1 删除优化 #

javascript
// 使用索引加速删除
db.users.createIndex({ status: 1 })
db.users.deleteMany({ status: "inactive" })

// 批量删除
db.users.deleteMany({ status: "inactive" })

// 分批删除大量数据
const batchSize = 1000
while (true) {
    const result = db.users.deleteMany(
        { status: "inactive" },
        { limit: batchSize }
    )
    if (result.deletedCount === 0) break
}

8.2 删除与drop #

javascript
// 删除所有文档(保留索引)
db.users.deleteMany({})

// 删除集合(删除索引)
db.users.drop()
db.createCollection("users")

// 对于大量数据,drop更快
db.users.drop()

九、删除安全 #

9.1 删除前确认 #

javascript
// 删除前查询确认
const count = db.users.countDocuments({ status: "inactive" })
print(`将删除 ${count} 个文档`)

if (count > 0) {
    db.users.deleteMany({ status: "inactive" })
}

9.2 备份数据 #

javascript
// 删除前备份
db.users.find({ status: "inactive" }).forEach(doc => {
    db.users_backup.insertOne(doc)
})

db.users.deleteMany({ status: "inactive" })

9.3 使用事务 #

javascript
// 使用事务确保数据一致性
const session = db.getMongo().startSession()
session.startTransaction()

try {
    db.orders.deleteMany({ userId: ObjectId("...") }, { session })
    db.users.deleteOne({ _id: ObjectId("...") }, { session })
    session.commitTransaction()
} catch (error) {
    session.abortTransaction()
    print("删除失败: " + error.message)
}

十、删除错误处理 #

10.1 权限错误 #

javascript
// 处理权限错误
try {
    db.users.deleteMany({ status: "inactive" })
} catch (error) {
    if (error.code === 13) {
        print("权限不足")
    }
}

10.2 网络错误 #

javascript
// 处理网络错误
try {
    db.users.deleteMany({ status: "inactive" })
} catch (error) {
    if (error.name === "MongoNetworkError") {
        print("网络错误: " + error.message)
    }
}

10.3 固定集合错误 #

javascript
// 固定集合不能删除单个文档
db.logs.deleteOne({ _id: ObjectId("...") })
// 报错:cannot remove from a capped collection

// 解决:使用drop重建
db.logs.drop()
db.createCollection("logs", { capped: true, size: 10485760 })

十一、最佳实践 #

11.1 删除前检查 #

javascript
// 推荐:删除前检查
const count = db.users.countDocuments({ status: "inactive" })
if (count > 1000) {
    print("警告:将删除大量文档")
    // 确认后执行
}
db.users.deleteMany({ status: "inactive" })

11.2 使用软删除 #

javascript
// 推荐:使用软删除
db.users.updateOne(
    { _id: ObjectId("...") },
    { $set: { deleted: true, deletedAt: new Date() } }
)

// 不推荐:直接删除
db.users.deleteOne({ _id: ObjectId("...") })

11.3 分批删除 #

javascript
// 推荐:分批删除大量数据
const batchSize = 1000
while (true) {
    const result = db.users.deleteMany(
        { status: "inactive" },
        { limit: batchSize }
    )
    if (result.deletedCount === 0) break
}

// 不推荐:一次性删除大量数据
db.users.deleteMany({ status: "inactive" })  // 可能超时

十二、常见问题 #

12.1 删除速度慢 #

javascript
// 原因:索引过多、无索引、大量数据

// 解决:
// 1. 创建索引
db.users.createIndex({ status: 1 })

// 2. 分批删除
while (true) {
    const result = db.users.deleteMany({ status: "inactive" }, { limit: 1000 })
    if (result.deletedCount === 0) break
}

// 3. 使用drop
db.users.drop()

12.2 删除后空间未释放 #

javascript
// 压缩集合释放空间
db.runCommand({ compact: "users" })

// 重建集合
db.users.drop()
db.createCollection("users")

12.3 误删除恢复 #

javascript
// 使用备份恢复
mongorestore --db mydb --collection users /backup/mydb/users.bson

// 使用oplog恢复(复制集)
// 需要在删除后尽快操作

十三、总结 #

删除操作速查表:

方法 说明 示例
deleteOne 删除单个文档 db.coll.deleteOne({…})
deleteMany 删除多个文档 db.coll.deleteMany({…})
findOneAndDelete 查找并删除 db.coll.findOneAndDelete({…})

删除选项:

选项 说明
writeConcern 写关注
collation 排序规则
limit 限制删除数量

下一步,让我们学习基础查询!

最后更新:2026-03-27