Deleting Documents
1. Deleting Single Document
| Method | Returns |
| deleteOne(filter) | { acknowledged, deletedCount } |
| deleteOne(filter, {hint}) | Force index |
| Retryable | Yes |
2. Deleting Multiple Documents
| Method | Description |
| deleteMany(filter) | Delete all matches |
| deleteMany({}) | Delete all (keep indexes) |
| Retryable | No (multi op) |
3. Using findOneAndDelete()
| Option | Purpose |
| sort | Choose which doc to delete |
| projection | Returned fields |
| collation | String comparison rules |
const oldest = await db.queue.findOneAndDelete({}, { sort: { createdAt: 1 } });
4. Deleting with Filter Criteria
| Filter | Use |
{status: "expired"} | Status-based cleanup |
{createdAt: {$lt: cutoff}} | Age-based |
{_id: {$in: ids}} | Batch by id |
5. Handling Delete Results
| Field | Meaning |
| acknowledged | False if w:0 |
| deletedCount | Number actually removed |
| deletedCount === 0 | Filter matched nothing |
6. Setting Write Concern for Deletes
| Setting | Effect |
| w: "majority" | Wait for majority ack |
| j: true | Wait for journal commit |
| wtimeout | ms before failing |
7. Using Bulk Delete Operations
| Op | Effect |
| deleteOne | Single-match delete in bulk |
| deleteMany | Multi-match delete in bulk |
await db.events.bulkWrite([
{ deleteMany: { filter: { type: "debug" } } },
{ deleteOne: { filter: { _id: id } } },
], { ordered: false });
8. Deleting All Documents
| Approach | Trade-off |
| deleteMany({}) | Keeps indexes; slow on large collections |
| drop() + recreate | O(1) clear; must recreate indexes/validators |
| remove({}) DEPRECATED | Removed in 7.0+ |
9. Using TTL Indexes for Automatic Deletion
| Aspect | Detail |
| Create | db.sessions.createIndex({expireAt:1}, {expireAfterSeconds:0}) |
| Sweep | Background thread every 60s |
| Field type | BSON Date (or array of Dates) |
| Capped | Not supported on capped collections |
10. Implementing Soft Deletes
| Pattern | Detail |
| Flag field | {deletedAt: Date} + partial index excluding deleted |
| View | Create view filtering deletedAt: null |
| TTL purge | TTL index on deletedAt for eventual hard delete |
db.posts.createIndex({deletedAt: 1}, {partialFilterExpression: {deletedAt: {$exists: true}}, expireAfterSeconds: 86400 * 30});
await db.posts.updateOne({_id: id}, {$set: {deletedAt: new Date()}});