Remove Documents
Learn how to delete documents from MongoDB using deleteOne(), deleteMany(), findOneAndDelete(), and drop(). Understand safe deletion practices, soft deletes, and how to bulk remove data efficiently.
Removing data is a critical operation that needs to be done carefully. MongoDB provides several methods for deleting documents, from removing a single document to wiping an entire collection. This episode covers all deletion methods and best practices.
deleteOne() — Remove First Match
// Delete the first document matching the filter
db.users.deleteOne({ email: "test@example.com" })
Output:
{ acknowledged: true, deletedCount: 1 }
// Delete by _id (most precise)
db.users.deleteOne({ _id: ObjectId("65a1b2c3d4e5f6a7b8c9d0e1") })
deleteMany() — Remove All Matches
// Delete all inactive users
db.users.deleteMany({ isActive: false })
// Delete all posts older than a year
db.posts.deleteMany({
createdAt: { $lt: new Date("2023-01-01") }
})
// Delete all documents in a collection (empty filter)
db.tempData.deleteMany({})
// Warning: This removes ALL documents but keeps the collection and indexes
findOneAndDelete() — Delete and Return
Unlike deleteOne(), this returns the deleted document so you can use its data:
// Delete and return the document
const deleted = db.queue.findOneAndDelete(
{ status: "pending" },
{ sort: { createdAt: 1 } } // Delete the oldest pending item
)
// The 'deleted' variable contains the full document that was removed
// Useful for: job queues, task processing, undo operations
drop() — Remove Entire Collection
// Drop the collection — removes all documents, indexes, and the collection itself
db.temporaryLogs.drop()
// Returns: true
// Compared to deleteMany({}):
// deleteMany({}) — removes all documents but keeps the collection and indexes
// drop() — removes everything including the collection structure
Conditional Deletion Patterns
// Delete users who haven't logged in for 6 months
const sixMonthsAgo = new Date();
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);
db.users.deleteMany({
lastLogin: { $lt: sixMonthsAgo },
role: { $ne: "admin" } // Never delete admins
})
// Delete expired sessions
db.sessions.deleteMany({
expiresAt: { $lt: new Date() }
})
// Delete duplicate entries (keep the first, delete the rest)
const seen = new Set();
db.emails.find().forEach(doc => {
if (seen.has(doc.email)) {
db.emails.deleteOne({ _id: doc._id });
} else {
seen.add(doc.email);
}
})
Safe Deletion Practices
1. Always Test Your Filter First
// FIRST: Check what would be deleted
db.users.find({ isActive: false }).count()
// Output: 47
// Review a few documents
db.users.find({ isActive: false }).limit(5)
// THEN: Delete only if you're sure
db.users.deleteMany({ isActive: false })
2. Soft Deletes
Instead of permanently deleting, mark documents as deleted:
// Soft delete — mark as deleted instead of removing
db.users.updateOne(
{ _id: userId },
{
$set: {
isDeleted: true,
deletedAt: new Date(),
deletedBy: "admin"
}
}
)
// Query only non-deleted documents
db.users.find({ isDeleted: { $ne: true } })
// Restore a soft-deleted document
db.users.updateOne(
{ _id: userId },
{ $unset: { isDeleted: "", deletedAt: "", deletedBy: "" } }
)
// Permanently remove soft-deleted documents older than 30 days
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
db.users.deleteMany({
isDeleted: true,
deletedAt: { $lt: thirtyDaysAgo }
})
3. Backup Before Bulk Deletes
// Export data before deleting
// In terminal:
// mongodump --db myDB --collection users --query '{"isActive": false}' --out /backup/
// Then delete
db.users.deleteMany({ isActive: false })
TTL (Time-To-Live) Index — Automatic Deletion
MongoDB can automatically delete documents after a specified time using TTL indexes:
// Create a TTL index — documents expire 24 hours after createdAt
db.sessions.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 86400 } // 86400 seconds = 24 hours
)
// Documents inserted into this collection will auto-delete after 24 hours
db.sessions.insertOne({
userId: "user123",
token: "abc123",
createdAt: new Date() // This document will be deleted 24 hours from now
})
Deletion Performance
deleteOne()with_idfilter is the fastest — uses the primary indexdeleteMany()with indexed fields is efficientdeleteMany({})on large collections can be slow — considerdrop()instead- TTL indexes handle cleanup automatically with minimal performance impact
What's Next
You now know how to safely remove documents from MongoDB. In the next episode, we'll learn about projections — selecting only specific fields to return, which improves query performance and reduces network overhead.