deleteOne() - delete a single document
Syntax
collection(name).deleteOne(filter, options?)
Parameters
filter (required)
Type: Object
Filter criteria used to match documents to be deleted. Use MongoDB query operators.
//Delete specific user
await collection("users").deleteOne({ userId: "user123" });
//Use query operators
await collection("products").deleteOne({
price: { $lt: 10 },
stock: 0
});
options (optional)
Type: Object
Return value
Type: Promise<Object>
Return an object containing the results of the deletion:
{
deletedCount: 1, //Number of deleted documents (0 or 1)
acknowledged: true //Is the operation confirmed?
}
Core Features
✅ Only delete the first matching document
Even if multiple documents match the filter criteria, deleteOne() only deletes the first matching document.
//Even if there are multiple users with status="inactive", only the first one will be deleted
const result = await collection("users").deleteOne({ status: "inactive" });
console.log(result.deletedCount); //1 (or 0 if no match)
✅ Explicit cache invalidation
After deletion succeeds, monSQLize does not clear query caches by default. Use cache.invalidate or autoInvalidate: true when the write should clear cache.
//First query (from database)
const user = await collection("users").findOne(
{ userId: "user123" },
{ cache: 5000 }
);
//Delete user and precisely clear the cached query when needed
await collection("users").deleteOne(
{ userId: "user123" },
{
cache: {
invalidate: [{
operation: "findOne",
query: { userId: "user123" },
options: { cache: 5000 }
}]
}
}
);
//Query again (will not be returned from cache because it has been cleaned)
const deletedUser = await collection("users").findOne(
{ userId: "user123" },
{ cache: 5000 }
); // null
✅ Slow query monitoring
Delete operations that exceed the threshold (default 1000ms) will automatically record a warning log.
//Configure slow query threshold
const monsqlize = new MonSQLize({
slowQueryMs: 500 //Log warning after more than 500ms
});
//Slow delete operations will be logged
await collection("logs").deleteOne({
timestamp: { $lt: new Date("2024-01-01") }
});
//Log: [WARN] [deleteOne] Slow operation warning { duration: 650ms, ... }
Common scenarios
Scenario 1: Delete a single user
//Delete based on user ID
const result = await collection("users").deleteOne({ userId: "user123" });
if (result.deletedCount === 1) {
console.log("User has been deleted");
} else {
console.log("User does not exist");
}
Scenario 2: Cleaning up expired data
//Delete the first expired session
const result = await collection("sessions").deleteOne({
expiresAt: { $lt: new Date() }
});
console.log(`${result.deletedCount} expired sessions deleted`);
Scenario 3: Delete records in a specific state
//Delete the first pending task
const result = await collection("tasks").deleteOne({
status: "pending",
priority: { $lt: 3 }
});
if (result.deletedCount === 0) {
console.log("There are no low priority tasks to be deleted");
}
//Force the use of a specific index
const result = await collection("orders").deleteOne(
{
customerId: "cust123",
status: "cancelled"
},
{
hint: { customerId: 1, status: 1 }, //Use composite index
comment: "cleanup-cancelled-orders"
}
);
Scenario 5: Set operation timeout
//Limit the maximum execution time of delete operations
try {
const result = await collection("logs").deleteOne(
{ level: "debug" },
{ maxTimeMS: 2000 } //up to 2 seconds
);
} catch (error) {
if (error.code === ErrorCodes.OPERATION_TIMEOUT) {
console.error("Delete operation timed out");
}
}
Differences from other methods
vs deleteMany
//deleteOne - delete only one
await collection("users").deleteOne({ status: "inactive" });
//Result: Remove the first inactive user
//deleteMany - delete all matches
await collection("users").deleteMany({ status: "inactive" });
//Result: Remove all inactive users
vs findOneAndDelete
//deleteOne - only returns the delete count
const result1 = await collection("users").deleteOne({ userId: "user123" });
console.log(result1); // { deletedCount: 1, acknowledged: true }
//findOneAndDelete - returns deleted documents
const result2 = await collection("users").findOneAndDelete({ userId: "user456" });
console.log(result2); // { _id: ..., userId: "user456", name: "Alice", ... }
Error handling
Invalid filter criteria
try {
//Error: filter must be an object
await collection("users").deleteOne("user123");
} catch (error) {
console.error(error.code); // INVALID_ARGUMENT
console.error(error.message); // "filter must be of object type"
}
Operation timeout
try {
await collection("logs").deleteOne(
{ timestamp: { $lt: new Date("2020-01-01") } },
{ maxTimeMS: 100 } //very short timeout
);
} catch (error) {
if (error.code === ErrorCodes.OPERATION_TIMEOUT) {
console.error("Delete operation timed out");
}
}
Write attention error
try {
await collection("users").deleteOne(
{ userId: "user123" },
{
writeConcern: { w: "majority", wtimeout: 1000 }
}
);
} catch (error) {
if (error.code === ErrorCodes.WRITE_ERROR) {
console.error("Write operation failed:", error.message);
}
}
1. Use index
Make sure the fields in the filter are indexed:
//Create index first
await collection("users").createIndex({ userId: 1 });
//Then delete (index will be used)
await collection("users").deleteOne({ userId: "user123" });
2. Use index hints
For complex queries, explicitly specify which index to use:
await collection("orders").deleteOne(
{
customerId: "cust123",
status: "cancelled",
createdAt: { $lt: new Date("2024-01-01") }
},
{
hint: { customerId: 1, createdAt: 1 } //Use composite index
}
);
3. Set a reasonable timeout
//Avoid long blocking
await collection("logs").deleteOne(
{ level: "debug" },
{ maxTimeMS: 5000 } //5 seconds timeout
);
4. Use precise filters
//Good: Use exact criteria (fast lookup via index)
await collection("users").deleteOne({ userId: "user123" });
//Bad: Use range queries (may need to scan multiple documents)
await collection("users").deleteOne({ age: { $gt: 18 } });
Notes
⚠️ Deletion is irreversible
//Unable to recover after deletion
const result = await collection("users").deleteOne({ userId: "user123" });
//If records need to be retained, consider using soft delete (mark as deleted)
await collection("users").updateOne(
{ userId: "user123" },
{ $set: { deleted: true, deletedAt: new Date() } }
);
⚠️ Unsure of deletion order
If multiple documents match, which one to delete is undefined (unless using sorting):
//Not sure which inactive user to delete
await collection("users").deleteOne({ status: "inactive" });
//If determinism is required, use findOneAndDelete and specify the ordering
await collection("users").findOneAndDelete(
{ status: "inactive" },
{ sort: { createdAt: 1 } } //Delete the oldest created
);
⚠️ Deletion does not affect the index
Deleting a document does not delete the index, it is automatically updated.
⚠️ Scope of cache invalidation
autoInvalidate: true clears the cache for the entire collection, not just deleted documents:
//Delete a user and request collection-wide broad invalidation
await collection("users").deleteOne(
{ userId: "user123" },
{ autoInvalidate: true }
);
//The cache of all users collections will be cleared
//Include cached queries from other users
Sample code
For complete sample code, please refer to the delete runnable example.
MongoDB Documentation