<返回目录     Powered by claud/xia兄

第7课: 删除操作

deleteOne() - 删除单个文档

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

// 返回结果
{
    acknowledged: true,
    deletedCount: 1
}
警告:

删除操作不可逆!删除前请确认查询条件正确。

deleteMany() - 删除多个文档

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

// 返回结果
{
    acknowledged: true,
    deletedCount: 15
}

// 删除所有文档(危险操作!)
db.users.deleteMany({})

删除前先查询

// 最佳实践:删除前先查询确认
// 1. 先查询要删除的文档
db.users.find({ status: "inactive" })

// 2. 确认无误后再删除
db.users.deleteMany({ status: "inactive" })

// 3. 验证删除结果
db.users.countDocuments({ status: "inactive" })

按_id删除

// 根据_id删除(最精确)
db.users.deleteOne({ _id: ObjectId("507f1f77bcf86cd799439011") })

// 删除多个指定_id的文档
db.users.deleteMany({
    _id: {
        $in: [
            ObjectId("..."),
            ObjectId("..."),
            ObjectId("...")
        ]
    }
})

条件删除

// 删除过期数据
db.sessions.deleteMany({
    expiresAt: { $lt: new Date() }
})

// 删除空字段的文档
db.users.deleteMany({
    email: { $exists: false }
})

// 删除符合多个条件的文档
db.products.deleteMany({
    $and: [
        { stock: 0 },
        { lastUpdated: { $lt: new Date("2025-01-01") } }
    ]
})

findOneAndDelete() - 查找并删除

// 删除并返回被删除的文档
const deletedUser = db.users.findOneAndDelete(
    { name: "张三" }
)

// 返回被删除的文档内容
{
    _id: ObjectId("..."),
    name: "张三",
    age: 25,
    email: "zhangsan@example.com"
}

// 按排序删除第一个
db.users.findOneAndDelete(
    { status: "inactive" },
    { sort: { lastLogin: 1 } }  // 删除最久未登录的
)

删除集合

// 删除整个集合(包括索引)
db.users.drop()

// 返回true表示成功
true

// 删除集合但保留索引
db.users.deleteMany({})

删除数据库

// 切换到要删除的数据库
use testdb

// 删除当前数据库
db.dropDatabase()

// 返回结果
{ "ok" : 1 }
极度危险:

dropDatabase()会永久删除整个数据库及其所有集合和数据!生产环境请谨慎操作。

批量删除策略

// 分批删除大量数据(避免锁表)
let batchSize = 1000;
let deleted = 0;

while (true) {
    let result = db.logs.deleteMany(
        { createdAt: { $lt: new Date("2025-01-01") } },
        { limit: batchSize }
    );

    deleted += result.deletedCount;

    if (result.deletedCount < batchSize) {
        break;
    }

    sleep(100);  // 暂停100ms
}

print("Total deleted: " + deleted);

软删除模式

// 不真正删除,而是标记为已删除
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) }  // 30天前
})

实战示例

// 清理过期会话
db.sessions.deleteMany({
    expiresAt: { $lt: new Date() }
})

// 删除未激活的用户(注册超过7天未激活)
db.users.deleteMany({
    status: "pending",
    createdAt: { $lt: new Date(Date.now() - 7*24*60*60*1000) }
})

// 清理测试数据
db.orders.deleteMany({
    $or: [
        { status: "test" },
        { userId: { $regex: /^test_/ } }
    ]
})

// 删除重复数据(保留最新的)
db.users.aggregate([
    {
        $group: {
            _id: "$email",
            ids: { $push: "$_id" },
            count: { $sum: 1 }
        }
    },
    { $match: { count: { $gt: 1 } } }
]).forEach(doc => {
    doc.ids.shift();  // 保留第一个
    db.users.deleteMany({ _id: { $in: doc.ids } });
});

删除操作的返回值

// 检查删除结果
const result = db.users.deleteMany({ age: { $lt: 18 } });

if (result.deletedCount > 0) {
    print(`成功删除 ${result.deletedCount} 条记录`);
} else {
    print("没有找到匹配的文档");
}
最佳实践:
练习题:
  1. 删除所有状态为"inactive"的用户
  2. 删除创建时间超过1年的日志记录
  3. 删除库存为0且最后更新时间超过6个月的商品
  4. 实现软删除:标记用户为已删除而不是真正删除
  5. 查找并删除最早的一条消息记录
  6. 分批删除100万条过期数据