bigywater.tech
MongoDB · 64

E11000 错误信息里有什么

收到 E11000 duplicate key error 时,里面到底有什么信息?哪个索引冲突了、冲突的值是什么、能不能直接用?这篇把各种情形下的错误内容都打出来。

11000
E11000 重复键错误的错误码
230 对 5000
长字符串键冲突时 message 的长度与 keyValue 里完整值的长度
一次一个
一个文档违反两个唯一索引时一次只报一个

错误内容

实测 · 本机执行输出
  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 长度 5000

message 会被截断(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。

分步演示

E11000 错误信息
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / MongoDB 9.0.2(Homebrew 的 mongod、mongos)/ mongosh 2.12.0 / pymongo 4.18.3;每个实验在临时目录里起全新的 mongod(独立 dbpath,端口 9900 以上,只监听 127.0.0.1,WiredTiger 缓存 0.25 GB),需要副本集或分片集群时在本机起多个进程;命令输出来自真实的 mongosh,批量写入、计时与多线程用 pymongo;计时用 time.perf_counter,数字每次运行会有小幅抖动,ObjectId、时间戳等每次运行都不同。单节点;错误内容来自 mongosh 与 pymongo
    • 没有验证:分片集群上 E11000 的 keyValue 是否相同;副本集 secondary 上应用 oplog 时遇到重复键的处理;collation 唯一索引的 dup key 显示原值还是排序键;TTL、部分索引的冲突信息;老版本里 E11000 的 message 格式
    京ICP备2026067502号-1京公网安备11010502063487号