如何阻止PyMongo修改插入的字典?含批量插入场景疑问
Great question—this is a super common gotcha with PyMongo that trips up a lot of developers, myself included! Let me break down why this happens and how to fix it.
Why Does PyMongo Modify the Original Dictionary?
PyMongo’s default behavior is to add the auto-generated _id field directly to the document object you pass in. This design choice makes it easy to access the new document’s ID right after insertion without extra steps, but it’s definitely annoying when you need to keep your original data untouched.
Solutions to Keep Original Dictionaries Clean
1. Insert a Copy of the Document (Single Insert)
For individual documents, create a shallow copy using dict.copy() before inserting. This way, PyMongo modifies the copy instead of your original dictionary:
original_doc = {"name": "Alice", "email": "alice@example.com"} # Create a copy to insert doc_to_insert = original_doc.copy() collection.insert_one(doc_to_insert) # original_doc remains unchanged—no _id field added! print(original_doc) # Output: {"name": "Alice", "email": "alice@example.com"}
If your document has nested dictionaries or lists, use copy.deepcopy() instead to ensure all nested structures are duplicated:
import copy original_doc = {"name": "Bob", "profile": {"age": 30, "hobbies": ["hiking", "reading"]}} doc_to_insert = copy.deepcopy(original_doc) collection.insert_one(doc_to_insert)
2. Batch Insert with Copies (insert_many)
For bulk inserts, use a list comprehension to create copies of all documents in your original list. This avoids having to modify each one manually:
original_docs = [ {"name": "Charlie"}, {"name": "Diana"}, {"name": "Eve"} ] # Generate a list of copies docs_to_insert = [doc.copy() for doc in original_docs] collection.insert_many(docs_to_insert) # original_docs stays clean—none have the _id field for doc in original_docs: print(doc) # No _id in any of these
Again, use copy.deepcopy() in the list comprehension if you have nested data structures.
3. Alternative: Fetch IDs from Insert Results (If You Need Them)
If you need access to the generated _id values but don’t want to modify the original documents, you can get them directly from the insertion result object instead:
# For insert_one result = collection.insert_one(original_doc) new_id = result.inserted_id # For insert_many result = collection.insert_many(original_docs) new_ids = result.inserted_ids # List of all generated _id values
Note: Even with this approach, PyMongo will still modify the original documents unless you pass copies. So this is just a way to get the IDs without relying on the modified docs—you still need to use copies to keep originals clean.
Is There a Way to Disable This Behavior?
Unfortunately, PyMongo doesn’t have a built-in parameter to turn off this modification of the original document. The core team designed it this way for convenience in common use cases, so the copy-based approach is the standard workaround.
内容的提问来源于stack exchange,提问作者ramazan polat

