最稳妥解法是直接捕获DuplicateKeyError异常,而非泛化catch Exception;需显式导入pymongo.errors.DuplicateKeyError,利用e.details.get('keyPattern')精准定位冲突索引。
直接捕获 DuplicateKeyError 是最稳妥的解法,不是“try-catch 万能”,而是 MongoDB 驱动明确抛出的、可精准识别的异常类型。
别用 except Exception,它会吞掉网络中断、权限不足等真正需要报警的问题。必须显式导入并捕获专用异常:
from pymongo.errors import DuplicateKeyErrorinsert_one() 和 insert_many() 都会触发该异常;update_one(upsert=True) 不会抛这个错,但可能意外覆盖字段e.details.get('keyPattern'),能告诉你冲突的是哪个索引(比如 {'email': 1}),比解析错误字符串可靠得多ordered: false 是关键开关——否则第一个 E11000 就让整批操作停摆。但注意:它只是跳过失败项,不是静默成功。
result.writeErrors,过滤 err.code === 11000(注意是数字 11000,不是字符串 "E11000")upsert: true 来“自动去重”:它本质是查+改/插,语义不符,且高并发下两个请求同时查不到,仍会双写触发 E11000
索引没生效或字段值有隐藏差异,不是代码逻辑问题。
db.collection.getIndexes() 确认索引状态是 "ready",且 "unique": true
aggregate 查 { $group: { _id: { field: "$field" }, count: { $sum: 1 } } } 找 count > 1 的项null 值处理都可能绕过校验——加 collation: { locale: "en", strength: 2 } 或用 sparse: true 处理 null 场景你没设 _id,MongoDB 会自动生成 ObjectId;但如果你手动传了字符串(比如前端传的 "507f1f77bcf86cd799439011"),而没转成 ObjectId,就会存成字符串类型,导致索引失效或误判重复。
new ObjectId(idStr)(Node.js)或 ObjectId(id_str)(Python)_id,极易重复;真要可控,用 UUID 或服务端生成的雪花 IDdropIndex 比 dropCollection 更安全真正麻烦的不是报错本身,而是错误发生时你不知道冲突到底来自哪条数据、哪个索引、甚至是不是同一条数据被反复提交。把 keyPattern 和 dup key 内容打出来,比猜强十倍。
小米路由器3G怎么恢复出厂设置(小米路由器3G该如何恢复出厂设置)
小米路由器3g和4a千兆版哪个好(小米路由器3g和4a千兆版对比区别)
Sensor Tower:ChatGPT全球份额跌破50%,Gemini与Claude加速追赶
OpenAI提速狂飙16倍!GPT-5.6多智能体V2上线,741轮怪物对话1秒打开
“十五五”时期 煤矿危险繁重岗位将由机器人替代
waytouniverse/ppt-generator:从 Markdown 大纲生成风格统一的 PPT 图片