MongoDB插入重复文档报DuplicateKeyError,重新实例化对象可正常插入
解决Pymongo重复插入同一对象的DuplicateKeyError问题
这个问题其实是Python可变对象特性 + MongoDB插入行为共同导致的,我给你一步步拆解清楚:
错误原因分析
先看你的代码逻辑:
jim = User("xx2", "password") mongo.db.users.insert_one(jim.jsonDoc)
当你第一次运行这段代码时,jim.jsonDoc是一个没有_id字段的字典。MongoDB在插入文档时,因为你没手动指定主键,会自动给这个字典添加一个唯一的_id字段(也就是你提到的ObjectID)。
关键细节来了:Python的字典是可变对象,insert_one()方法会直接修改你传入的这个字典本身——也就是说,第一次插入完成后,jim.jsonDoc里已经多了一个_id键,值就是第一次生成的那个ObjectID。
当你重新运行同一个单元格时,你还是在尝试插入同一个已经带有_id的字典。而MongoDB的_id是集合的唯一主键,自然就触发了E11000 duplicate key error。
至于重新实例化User对象就能正常插入,是因为新的User实例会生成一个全新的、没有_id的字典,MongoDB会再次为它生成新的ObjectID,所以不会冲突。
两种实用解决方案
方案1:插入字典的副本
每次插入时,传递原字典的副本,这样MongoDB修改的是副本,原字典不会被带上_id:
jim = User("xx2", "password") mongo.db.users.insert_one(jim.jsonDoc.copy())
方案2:修改User类,每次返回新字典
推荐这种更优雅的方式,给User类添加一个生成字典的方法,每次调用都返回全新的字典:
class User: def __init__(self, email, password, username=None, image_file=None): self.email = email self.password = password self.username = username self.image_file = image_file # 新增方法,每次调用都生成不带_id的新字典 def to_dict(self): return { "email": self.email, "password": self.password, "username": self.username, "image_file": self.image_file } def __repr__(self): return f"User('{self.username}', '{self.email}', '{self.image_file}')" # 插入时调用to_dict()获取新字典 jim = User("xx2", "password") mongo.db.users.insert_one(jim.to_dict())
这样不管你多少次运行单元格,每次插入的都是不带_id的新字典,MongoDB都会自动生成唯一的ObjectID,不会再报错。
内容的提问来源于stack exchange,提问作者warnerm06
相关产品推荐
相关产品推荐

