【问题标题】:MongoDB - Why does the _id index not throwing an error on duplicate entries?MongoDB - 为什么 _id 索引不会在重复条目上引发错误?
【发布时间】:2016-07-13 09:44:42
【问题描述】:

我对 NoSQL 数据库完全陌生,目前正在使用 MongoDB。

我试图理解为什么默认的_id 索引在upserting a duplicate _id 文档时不会引发错误。

如文档中所述,_id 默认是唯一索引

(虽然这里没有显示唯一标志..)

> db.foo.getIndexes();
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.foo"
    }
]
>

所以当upserting 文档(以空集合开头)时,
如果首先插入它然后似乎“忽略”它。

> db.foo.update({ _id: 'doe123'}, { _id: 'doe123', name: 'John Doe'}, { upsert: true});
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "doe123" })

> db.foo.update({ _id: 'doe123'}, { _id: 'doe123', name: 'John Doe'}, { upsert: true});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

所以我尝试了另一件事并在“名称”上创建了一个unique index

插入重名的结果:

> db.foo.update({ _id: 'foo456'}, { _id: 'foo456', name: 'John Doe'}, { upsert: true});
WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "E11000 duplicate key error collection: test.foo index: name_1 dup key: { : \"John Doe\" }"
    }
})

为什么我在重复的_id没有收到这种错误?


编辑:我使用的是 MongoDB v.3.2.3

【问题讨论】:

    标签: mongodb unique-index nosql


    【解决方案1】:

    在第一种情况下没有理由显示重复索引错误,因为它只是尝试使用相同的值更新同一记录的 _idname 字段。

    如果你愿意尝试

      db.foo.update({ _id: '1098'}, { _id: 'doe123', name: 'John Doe'}, { upsert: true});
    

    您将收到错误,因为查询正在尝试使用一些现有的 _id 值更新具有不同 _id 的记录。

    在第二种情况下,您首先使用name 字段创建了一条记录,然后您尝试在另一条记录中更新相同的名称,这将导致错误,因为name 是唯一索引。

    编辑:-

    如果你正在尝试

     db.foo.insert({ _id: 'doe123', name: 'John Doe'});
    

    会给你错误,因为在这种情况下你试图插入一条已经存在的记录,即_id 是唯一的,并且你试图创建一个具有相同_id 值的记录。

    upsert:true :- 如果 upsert 为真并且没有文档符合查询条件,update() 插入单个文档。

    如果 upsert 为真并且有符合查询条件的文档,update() 执行更新。

    【讨论】:

    • 我尝试了一些方法,但使用 insert 而不是 upsert 得到了我所期望的异常/错误:"E11000 duplicate key error collection: test.foo index: _id_ dup key: { : \"doe123\" }"。那么为什么 insert 会抛出错误,但 upsert 不会呢?仅仅因为它查找“我必须更新一些东西吗?不需要?好吧,我什么都不做”
    • upsert : true 表示如果字段不存在,它将插入,否则只会更新值。在insert 的情况下,它将尝试插入记录,该记录实际上具有_id 的重复值。我希望现在很清楚。
    • 所以它基本上是用它自己“覆盖” _id 'doe123',如果已经存在这个 _id 的记录?
    • 无法理解您的问题。能说清楚点吗?
    猜你喜欢
    • 2013-10-27
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 2022-01-24
    • 1970-01-01
    • 2017-01-06
    • 2014-12-11
    • 1970-01-01
    相关资源
    最近更新 更多