【mogoDB】mongoDB唯一性约束索引 {unique: true} 选项

mongoDB创建索引失败解析

> use testDB

> db.T_Test.ensureIndex({"oid":1,"day":1,"codeId":1},{unique:true},{background: 1});
{
        "ok" : 0,
        "errmsg" : "E11000 duplicate key error collection: testDB.T_Test index: oid_1_day_1_codeId_1 dup key: { : \"64d0ada0d08e8f52db791c71\", : \"2023-10-21\", : \"5ed1a7875c1b4bf39ea7123b2dd16788\" }",
        "code" : 11000,
        "codeName" : "DuplicateKey"
}

您在创建 MongoDB 索引时遇到了 E11000 duplicate key error 错误。
这个错误表示在您尝试创建唯一索引时,MongoDB 检测到已有的文档在目标字段组合上存在重复数据,违反了唯一性约束。

错误信息解析

  • 错误代码11000,这是一个 MongoDB 的常见错误代码,表示违反了唯一约束。
  • 错误消息E11000 duplicate key error collection: cloudflow.T_Template_UseRecord index: oid_1_day_1_codeId_1
    • 该错误发生在名为 T_Template_UseRecord 的集合中,您试图创建一个复合唯一索引,索引的字段为 "oid", "day", "codeId"
  • 重复的键dup key: { : "64d0ada0d08e8f52db791c71", : "2023-10-21", : "5ed1a7875c1b4bf39ea7123b2dd16788" }
    • 这部分说明在集合中已经存在一个文档,它的 "oid"64d0ada0d08e8f52db791c71"day"2023-10-21"codeId"5ed1a7875c1b4bf39ea7123b2dd16788。因此,这个字段组合已经存在重复的记录,违反了唯一性索引的要求。

错误的原因

您试图在集合 T_Template_UseRecord 上创建一个 唯一索引,该索引涵盖了字段 oiddaycodeId。MongoDB 在创建索引时,会确保该组合在集合中的所有文档都是唯一的。但是,集合中已经存在至少一对重复的 oid, day, 和 codeId 组合,因此导致了这个错误。

解决方案

  1. 检查重复数据

    • 首先,您可以查询集合中是否已经存在相同的 oid, day, codeId 组合。可以通过以下查询来确认重复的记录:
      db.T_Test.aggregate([
        { $group: { _id: { oid: "$oid", day: "$day", codeId: "$codeId" }, count: { $sum: 1 } } },
        { $match: { count: { $gt: 1 } } }
      ])
      
      这个聚合查询将返回所有重复的 oid, day, codeId 组合及其重复次数。
  2. 清理重复数据

    • 如果发现有重复数据,您需要决定如何处理这些重复文档。常见的做法包括:
      • 删除重复记录:您可以删除重复的文档,只保留一条。
      • 修改数据:如果重复是由于某些业务逻辑错误导致的,您可能需要修改或合并重复的数据。

    示例删除重复记录(假设您已经查找到重复项):

    db.T_Test.remove({ "oid": "64d0ada0d08e8f52db791c71", "day": "2023-10-21", "codeId": "5ed1a7875c1b4bf39ea7123b2dd16788" });
    
  3. 重新创建索引

    • 一旦解决了重复数据问题,就可以尝试重新创建索引:
      db.T_Test.createIndex({"oid": 1, "day": 1, "codeId": 1}, {unique: true, background: true});
      

其他注意事项

  • 索引的性能:在生产环境中创建索引时,建议使用 {background: true} 选项,这样创建索引的过程不会阻塞其他操作。不过,在某些版本的 MongoDB 中,background 选项已经不再推荐使用。
  • 数据迁移和清理:在处理重复数据时,确保理解数据的业务逻辑,避免误删或修改重要的数据。

总结

您的错误主要是由于数据中存在违反唯一约束的重复项。解决方法是首先找出并清理重复的记录,然后再重新创建索引。这可以确保您的数据在新索引生效后是唯一的。

创建索引,加不加 unique: true 选项,有什么区别?

在 MongoDB 中,创建索引时是否使用 unique: true 选项,区别非常大,主要体现在 索引的约束行为 上。下面是加上 unique: true 与不加该选项时的主要区别:

1. unique: true 选项的作用

  • 唯一性约束:当您在创建索引时使用 unique: true 选项时,MongoDB 会保证该索引所包含的字段组合在集合中的每一条记录都是唯一的。
  • 如果您尝试插入或更新一条记录,导致该记录在该字段组合上的值与已有记录重复,MongoDB 会返回一个错误并拒绝操作。错误代码为 11000E11000 duplicate key error)。

示例:使用 unique: true

db.collection.createIndex({ "field1": 1, "field2": 1 }, { unique: true });
  • 这个索引会保证 field1field2 的组合在集合中是唯一的。两个文档如果在 field1field2 上的值完全相同,则会导致插入或更新失败。

错误示例:

假设有一个字段组合 field1: 1, field2: 1,如果已经有一条记录 { field1: "A", field2: "B" },然后插入另一条记录 { field1: "A", field2: "B" },MongoDB 会返回一个错误:

E11000 duplicate key error collection: mydb.collection index: field1_1_field2_1 dup key: { : "A", : "B" }

2. 不使用 unique: true 选项(默认行为)

  • 非唯一索引:如果不使用 unique: true,索引将是一个普通的非唯一索引。这意味着 MongoDB 会创建一个索引来加速查询,但不会对字段值组合的唯一性进行任何强制约束。
  • 在这种情况下,即使字段组合的值在多个文档中重复,插入或更新也不会失败。

示例:没有 unique: true

db.collection.createIndex({ "field1": 1, "field2": 1 });
  • 这个索引会加速基于 field1field2 的查询,但不会阻止两个文档中有相同的 field1field2 的组合。

不会报错的情况:

假设已经存在一条记录 { field1: "A", field2: "B" },然后您插入一条记录 { field1: "A", field2: "B" },由于没有设置 unique: true,MongoDB 允许这个操作,而不会报错。

3. 性能区别

  • 唯一索引(unique: true:唯一索引的维护成本略高,因为 MongoDB 在每次插入、更新或删除文档时,需要检查是否会违反唯一性约束。这意味着每次操作都会额外进行一次检查,性能开销相对较大。
  • 非唯一索引:非唯一索引的性能开销通常较低,因为它不需要验证唯一性,只是简单地加速查询。它通常比唯一索引的维护成本要低。

4. 适用场景

  • 唯一索引(unique: true:适用于您希望确保某些字段或字段组合的值在整个集合中是唯一的。例如:
    • 用户名、电子邮件地址等需要全局唯一的字段。
    • 唯一标识符(例如,ID 字段)等。
  • 非唯一索引:适用于希望通过某些字段加速查询,但不需要确保该字段的值在集合中唯一的场景。例如:
    • 查询频繁的字段(如 date, status 等),但是这些字段值可能有重复。

5. 如何使用索引

  • 查询性能:无论是否加 unique: true,都能加速查询操作。如果需要频繁查询 field1field2 的组合,创建索引能显著提高查询效率。
  • 插入与更新:使用 unique: true 的索引会对插入和更新操作产生影响。如果数据库中已有相同的字段组合,插入或更新会失败。而没有 unique: true 的索引,则不会有此限制。

总结

  • unique: true:在创建索引时强制保证该字段(组合)的值在集合中唯一,确保数据一致性;但会增加插入和更新时的验证开销。
  • 不使用 unique: true:只加速查询,不会强制字段值的唯一性,允许重复数据。性能开销相对较低,但可能会引入重复数据。

是否使用 unique: true 取决于您的应用需求:如果需要保证数据的唯一性,则使用 unique: true;如果只关心查询性能,不在乎重复数据,则可以省略该选项。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354