收到 E11000 duplicate key error 时,里面到底有什么信息?哪个索引冲突了、冲突的值是什么、能不能直接用?这篇把各种情形下的错误内容都打出来。
test> db.a.insertOne({_id: 1, email: "a@x.com"})
{ acknowledged: true, insertedId: 1 }
test> try { db.a.insertOne({_id: 1}) } catch (e) { ({name: e.name, code: e.code, message: e.message, keyPattern: e.keyPattern, keyValue: e.keyValue}) }
{
name: 'MongoServerError',
code: 11000,
message: 'E11000 duplicate key error collection: test.a index: _id_ dup key: { _id: 1 }',
keyPattern: { _id: 1 },
keyValue: { _id: 1 }
}
pymongo 里同一个错误:
DuplicateKeyError.code = 11000;str(e) = E11000 duplicate key error collection: test.a index: _id_ dup key: { _id: 1 }, full error: {'index': 0, 'code'…;e.details 的键 = ['code', 'errmsg', 'index', 'keyPattern', 'keyValue'];keyPattern = {'_id': 1};keyValue = {'_id': 1}message 含集合名、索引名和 dup key;结构化字段 keyPattern 与 keyValue 指出是哪个索引、哪个值。
email 重复 index=email_1 errmsg 的 dup key 部分: { email: "a@x.com" } keyPattern={'email': 1} keyValue={'email': 'a@x.com'}
复合 (org, seq) 重复 index=org_seq errmsg 的 dup key 部分: { org: "o1", seq: 1 } keyPattern={'org': 1, 'seq': 1} keyValue={'org': 'o1', 'seq': 1}
嵌套 profile.phone 重复 index=profile.phone_1 errmsg 的 dup key 部分: { profile.phone: "111" } keyPattern={'profile.phone': 1} keyValue={'profile.phone': '111'}单字段、复合、嵌套字段的 dup key 形状各不相同,但 keyValue 的键始终对应索引的键。
第 1 次报的是: {'email': 1}
第 2 次报的是: {'org': 1, 'seq': 1}违反多个唯一索引时一次只报一个,修好再试可能遇到下一个。
errmsg 长度 230 字符;dup key 部分: { s: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx…(共 162 字符);keyValue.s 长度 5000message 会被截断(230 字符),keyValue 保持完整,程序应读结构化字段。
第一次(新 email): ('created', ObjectId('6acc5622158f64966424c717'))
第二次(同一个 email): ('existing', ObjectId('6acc5622158f64966424c717'))先插入,冲突了就用 keyValue 查已有的文档,是常见的“获取或创建”写法。
writeErrors: [(1, 11000, {'k': 1}), (3, 11000, {'k': 2})];nInserted=2
update 把 k=3 改成 1:code=11000,details.errmsg=Plan executor error during update :: caused by :: E11000 duplicate key error collection: test.b inde…
# findOneAndUpdate 同样
test> try { db.b.findOneAndUpdate({k: 3}, {$set: {k: 2}}) } catch (e) { ({code: e.code, keyValue: e.keyValue}) }
{ code: 11000, keyValue: { k: 2 } }批量写入的 writeErrors 逐个列出下标、code 和 keyValue;update 与 findOneAndUpdate 也是同样的 11000。