Amazon DocumentDB 文档删除 #
一、删除方法概述 #
1.1 删除方法 #
text
删除方法:
├── deleteOne - 删除单个文档
├── deleteMany - 删除多个文档
├── findOneAndDelete - 查找并删除
└── remove - 已废弃,不推荐使用
1.2 删除注意事项 #
text
删除前考虑:
├── 确认删除条件
├── 检查是否有备份数据
├── 考虑使用软删除
├── 检查关联数据
└── 确认权限
二、deleteOne - 删除单个文档 #
2.1 基本用法 #
javascript
// 删除单个文档
db.users.deleteOne({ _id: ObjectId("...") })
// 返回结果
{
"acknowledged": true,
"deletedCount": 1
}
2.2 条件删除 #
javascript
// 根据条件删除
db.users.deleteOne({ email: "test@example.com" })
// 删除指定条件的第一个文档
db.logs.deleteOne(
{ level: "debug" },
{ sort: { timestamp: 1 } } // 删除最早的
)
2.3 删除选项 #
javascript
// 带写关注删除
db.users.deleteOne(
{ _id: ObjectId("...") },
{ writeConcern: { w: "majority" } }
)
三、deleteMany - 删除多个文档 #
3.1 基本用法 #
javascript
// 删除多个文档
db.users.deleteMany({ status: "inactive" })
// 返回结果
{
"acknowledged": true,
"deletedCount": 150
}
3.2 条件删除 #
javascript
// 删除过期数据
db.logs.deleteMany({
timestamp: { $lt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) }
})
// 删除无效数据
db.users.deleteMany({
$or: [
{ email: { $exists: false } },
{ email: null },
{ email: "" }
]
})
// 删除测试数据
db.products.deleteMany({
isTest: true
})
3.3 删除所有文档 #
javascript
// 删除集合中所有文档
db.users.deleteMany({})
// 注意:这会删除所有文档,但保留集合和索引
四、findOneAndDelete #
4.1 基本用法 #
javascript
// 查找并删除,返回被删除的文档
const deletedDoc = db.users.findOneAndDelete(
{ email: "test@example.com" }
)
// 返回被删除的文档
{
"_id": ObjectId("..."),
"name": "测试用户",
"email": "test@example.com"
}
4.2 带排序删除 #
javascript
// 删除最早的日志
const oldestLog = db.logs.findOneAndDelete(
{ level: "debug" },
{ sort: { timestamp: 1 } }
)
// 删除优先级最低的任务
const task = db.tasks.findOneAndDelete(
{ status: "pending" },
{ sort: { priority: 1, createdAt: 1 } }
)
4.3 带投影删除 #
javascript
// 只返回指定字段
const result = db.users.findOneAndDelete(
{ _id: ObjectId("...") },
{ projection: { name: 1, email: 1 } }
)
五、软删除模式 #
5.1 软删除实现 #
javascript
// 添加删除标记而不是真正删除
db.users.updateOne(
{ _id: ObjectId("...") },
{
$set: {
deleted: true,
deletedAt: new Date(),
deletedBy: "admin"
}
}
)
// 查询时排除已删除文档
db.users.find({ deleted: { $ne: true } })
// 查询已删除文档
db.users.find({ deleted: true })
5.2 软删除索引 #
javascript
// 创建部分索引,排除已删除文档
db.users.createIndex(
{ email: 1 },
{
unique: true,
partialFilterExpression: { deleted: { $ne: true } }
}
)
5.3 恢复软删除 #
javascript
// 恢复已删除文档
db.users.updateOne(
{ _id: ObjectId("..."), deleted: true },
{
$set: { deleted: false },
$unset: { deletedAt: "", deletedBy: "" }
}
)
5.4 定期清理 #
javascript
// 定期永久删除软删除数据
db.users.deleteMany({
deleted: true,
deletedAt: { $lt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) }
})
六、批量删除策略 #
6.1 分批删除 #
javascript
// 大数据量分批删除
function batchDelete(collection, filter, batchSize = 1000) {
let totalDeleted = 0;
while (true) {
const result = collection.deleteMany(
filter,
{ limit: batchSize }
);
totalDeleted += result.deletedCount;
print(`Deleted ${result.deletedCount} documents, total: ${totalDeleted}`);
if (result.deletedCount < batchSize) {
break;
}
// 暂停一下,避免压力过大
sleep(100);
}
return totalDeleted;
}
// 使用示例
batchDelete(db.logs, { timestamp: { $lt: new Date("2023-01-01") } });
6.2 使用聚合删除 #
javascript
// 查找并删除
const idsToDelete = db.logs.find({
timestamp: { $lt: new Date("2023-01-01") }
}, { _id: 1 }).map(doc => doc._id);
db.logs.deleteMany({
_id: { $in: idsToDelete }
});
七、级联删除 #
7.1 手动级联删除 #
javascript
// 删除用户及其关联数据
async function deleteUserWithRelations(userId) {
const session = client.startSession();
try {
session.startTransaction();
// 删除用户订单
await db.orders.deleteMany(
{ userId: userId },
{ session }
);
// 删除用户评论
await db.comments.deleteMany(
{ userId: userId },
{ session }
);
// 删除用户
await db.users.deleteOne(
{ _id: userId },
{ session }
);
await session.commitTransaction();
print("用户及相关数据删除成功");
} catch (error) {
await session.abortTransaction();
print("删除失败: " + error.message);
} finally {
await session.endSession();
}
}
7.2 使用变更流实现 #
javascript
// 监听删除事件,自动清理关联数据
const changeStream = db.users.watch([
{ $match: { operationType: "delete" } }
]);
changeStream.on("change", async (change) => {
const userId = change.documentKey._id;
// 删除关联数据
await db.orders.deleteMany({ userId: userId });
await db.comments.deleteMany({ userId: userId });
});
八、删除性能优化 #
8.1 索引使用 #
javascript
// 确保删除条件使用索引
db.logs.createIndex({ timestamp: 1 })
// 使用索引字段删除
db.logs.deleteMany({
timestamp: { $lt: new Date("2023-01-01") }
})
8.2 删除vs truncate #
text
性能对比:
├── deleteMany({})
│ ├── 保留索引
│ ├── 记录操作日志
│ ├── 可以回滚
│ └── 较慢
│
└── drop() + createCollection()
├── 删除所有索引
├── 不记录操作日志
├── 无法回滚
└── 更快
8.3 优化建议 #
text
删除优化:
├── 使用索引字段作为条件
├── 大批量删除分批进行
├── 低峰期执行大批量删除
├── 考虑使用TTL索引自动删除
└── 监控删除性能
九、TTL索引自动删除 #
9.1 创建TTL索引 #
javascript
// 创建TTL索引,自动删除过期文档
db.sessions.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 3600 } // 1小时后删除
)
// 插入文档
db.sessions.insertOne({
sessionId: "session123",
userId: "user001",
createdAt: new Date()
})
9.2 TTL索引特点 #
text
TTL索引说明:
├── 后台线程定期扫描
├── 删除时间不精确(约60秒扫描一次)
├── 只能用于单字段索引
├── 字段必须是日期类型
└── 不影响查询性能
十、删除安全最佳实践 #
10.1 删除前验证 #
javascript
// 安全删除函数
function safeDelete(collection, filter, options = {}) {
// 检查删除条件
if (!filter || Object.keys(filter).length === 0) {
throw new Error("删除条件不能为空");
}
// 预览将要删除的文档
const count = collection.countDocuments(filter);
print(`将要删除 ${count} 个文档`);
if (options.preview) {
return collection.find(filter).limit(10).toArray();
}
// 确认删除
if (options.confirm !== true) {
throw new Error("需要确认删除操作");
}
return collection.deleteMany(filter);
}
// 使用示例
safeDelete(db.users, { status: "inactive" }, { preview: true });
safeDelete(db.users, { status: "inactive" }, { confirm: true });
10.2 删除审计 #
javascript
// 记录删除操作
async function deleteWithAudit(collection, filter, operator) {
// 查找要删除的文档
const docsToDelete = await collection.find(filter).toArray();
// 记录到审计日志
await db.auditLogs.insertMany(docsToDelete.map(doc => ({
operation: "delete",
collection: collection.collectionName,
documentId: doc._id,
document: doc,
operator: operator,
timestamp: new Date()
})));
// 执行删除
return collection.deleteMany(filter);
}
10.3 权限控制 #
javascript
// 创建只读用户(不能删除)
db.createUser({
user: "readonly",
pwd: "password",
roles: [
{ role: "read", db: "mydb" }
]
})
// 创建有删除权限的用户
db.createUser({
user: "admin",
pwd: "password",
roles: [
{ role: "readWrite", db: "mydb" }
]
})
十一、常见问题 #
11.1 删除后空间未释放 #
text
说明:
├── DocumentDB不会立即释放磁盘空间
├── 空间标记为可重用
├── 后续写入会优先使用
└── 可通过compact命令整理
11.2 删除操作超时 #
javascript
// 问题:大批量删除超时
// 解决:分批删除
function batchDeleteSafe(collection, filter, batchSize = 1000) {
let deleted = 0;
while (true) {
// 获取一批ID
const ids = collection.find(filter, { _id: 1 })
.limit(batchSize)
.map(doc => doc._id);
if (ids.length === 0) break;
// 删除这批文档
const result = collection.deleteMany({ _id: { $in: ids } });
deleted += result.deletedCount;
if (ids.length < batchSize) break;
}
return deleted;
}
11.3 误删除恢复 #
text
恢复方法:
├── 从备份恢复
├── 使用时间点恢复(PITR)
├── 从审计日志恢复
└── 使用变更流日志
十二、总结 #
12.1 删除方法对比 #
| 方法 | 用途 | 返回值 |
|---|---|---|
| deleteOne | 删除单个文档 | 删除计数 |
| deleteMany | 删除多个文档 | 删除计数 |
| findOneAndDelete | 查找并删除 | 被删除文档 |
12.2 最佳实践总结 #
text
删除最佳实践:
├── 使用软删除保护重要数据
├── 删除前预览和确认
├── 记录删除审计日志
├── 大批量删除分批进行
├── 使用TTL索引自动清理
└── 确保有备份恢复方案
下一步,让我们学习基础查询!
最后更新:2026-03-27