W3docs

MongoDB Delete

Learn how to delete documents from MongoDB in Python using PyMongo's delete_one() and delete_many() with filters, error handling, and safe patterns.

PyMongo provides two methods for removing documents from a collection: delete_one() removes the first matching document, and delete_many() removes every matching document. Both are precise, filter-driven operations — you specify exactly which documents to target using the same query syntax as find().

This chapter covers:

  • delete_one() — remove a single document
  • delete_many() — remove multiple documents (including all documents)
  • Reading the DeleteResult object
  • Filter operators that make deletions precise
  • Error handling and safety practices
  • When to delete documents versus dropping the whole collection

Prerequisites: Python 3.8+, PyMongo installed (pip install pymongo), and a running MongoDB server. See MongoDB Get Started for setup, and MongoDB Insert to understand how documents get into a collection in the first place.

Connecting and Selecting a Collection

Every delete operation needs a MongoClient, a database, and a collection:

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["mydatabase"]
col = db["customers"]

All examples below assume col is defined this way.

Deleting One Document with delete_one()

delete_one(filter) finds the first document that matches the filter and deletes it. If multiple documents match, only one is removed (MongoDB's natural order determines which one).

result = col.delete_one({"name": "Alice"})
print(result.deleted_count)  # 1 if a match was found, 0 if not

delete_one() never raises an error when no document matches — it returns a DeleteResult with deleted_count = 0.

Matching on a specific field value

# Delete the customer whose name is "Bob"
result = col.delete_one({"name": "Bob"})

if result.deleted_count == 1:
    print("Document deleted.")
else:
    print("No matching document found.")

Matching on a nested field

Use dot notation to target fields inside embedded documents:

# Delete the first customer whose city is "London"
result = col.delete_one({"address.city": "London"})
print(result.deleted_count)  # 1 or 0

Deleting Multiple Documents with delete_many()

delete_many(filter) removes every document that matches the filter. Use it when you need to clean up a set of records in one call.

# Delete all customers whose address starts with "S"
result = col.delete_many({"address": {"$regex": "^S"}})
print(result.deleted_count, "documents deleted")

Deleting all documents in a collection

Pass an empty filter {} to remove every document. The collection itself and its indexes remain — only the documents are gone:

result = col.delete_many({})
print(result.deleted_count, "documents deleted")

Warning: delete_many({}) on a production collection is irreversible. Always double-check your filter and take a backup before running bulk deletes. If you want to remove the collection entirely (documents and indexes), use col.drop() — see MongoDB Drop Collection.

The DeleteResult Object

Both methods return a DeleteResult. The two properties you will use most often are:

PropertyTypeDescription
deleted_countintNumber of documents actually deleted
acknowledgedboolTrue if the server confirmed the write; False for unacknowledged writes
result = col.delete_many({"status": "inactive"})
print(f"Deleted: {result.deleted_count}")
print(f"Acknowledged: {result.acknowledged}")

Filter Operators for Precise Deletions

The same query operators used in find() work inside delete filters.

Delete by comparison

# Delete all orders with a quantity less than 10
col.delete_many({"qty": {"$lt": 10}})

# Delete all orders with a quantity greater than or equal to 100
col.delete_many({"qty": {"$gte": 100}})

Delete by regular expression

# Delete all customers whose name starts with "A" (case-sensitive)
col.delete_many({"name": {"$regex": "^A"}})

Delete by existence of a field

# Delete all documents that have no "email" field
col.delete_many({"email": {"$exists": False}})

Delete by value in a list

# Delete all documents whose status is either "cancelled" or "expired"
col.delete_many({"status": {"$in": ["cancelled", "expired"]}})

Error Handling

Wrap delete operations in a try/except block to handle the two most common failure modes:

  • pymongo.errors.OperationFailure — the server rejected the operation (e.g., the connected user lacks remove privileges on the collection).
  • pymongo.errors.ConnectionFailure — the network connection to MongoDB was lost.
import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
col = client["mydatabase"]["customers"]

try:
    result = col.delete_many({"status": "inactive"})
    print(f"{result.deleted_count} documents deleted.")
except pymongo.errors.OperationFailure as e:
    print(f"Server error: {e}")
except pymongo.errors.ConnectionFailure as e:
    print(f"Connection error: {e}")

Practical Example: Full Workflow

This example seeds a collection, runs targeted deletes, and verifies the outcome:

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")
col = client["mydatabase"]["customers"]

# 1. Start clean
col.drop()

# 2. Insert sample documents
col.insert_many([
    {"name": "Alice", "city": "Oslo",   "active": True},
    {"name": "Bob",   "city": "Sydney", "active": False},
    {"name": "Carol", "city": "Seattle","active": False},
    {"name": "Dave",  "city": "Sofia",  "active": True},
])
print("Inserted:", col.count_documents({}))  # 4

# 3. Delete the one inactive customer named "Bob"
r1 = col.delete_one({"name": "Bob", "active": False})
print("delete_one:", r1.deleted_count)  # 1

# 4. Delete all customers in cities that start with "S"
r2 = col.delete_many({"city": {"$regex": "^S"}})
print("delete_many (city ^S):", r2.deleted_count)  # 2 (Carol/Seattle, Dave/Sofia)

# 5. Check what remains
remaining = list(col.find({}, {"_id": 0}))
print("Remaining:", remaining)  # [{'name': 'Alice', 'city': 'Oslo', 'active': True}]

Expected output:

Inserted: 4
delete_one: 1
delete_many (city ^S): 2
Remaining: [{'name': 'Alice', 'city': 'Oslo', 'active': True}]

Delete Documents vs. Drop a Collection

These two operations are frequently confused:

OperationDocuments removedCollection removedIndexes removedSpeed
col.delete_many({})AllNoNoSlower on large sets
col.drop()AllYesYesVery fast

Choose delete_many({}) when you need to empty a collection but keep its indexes and schema validators intact. Choose col.drop() when you want a completely clean slate — for example, between test runs or during a schema migration. See MongoDB Drop Collection for details on drop().

Summary

  • delete_one(filter) removes the first matching document; delete_many(filter) removes all matching documents.
  • Both return a DeleteResult — check deleted_count to confirm what was removed.
  • An empty filter {} in delete_many() removes all documents from the collection.
  • Use MongoDB query operators ($regex, $lt, $in, $exists, …) to build precise filters.
  • Wrap operations in try/except to handle OperationFailure and ConnectionFailure.
  • To remove the collection itself, use col.drop() instead.

Related chapters:

Was this page helpful?