MongoDB插入引发重复键错误

Posted

技术标签:

【中文标题】MongoDB插入引发重复键错误【英文标题】:MongoDB insert raises duplicate key error 【发布时间】:2013-07-05 22:30:09 【问题描述】:

尝试向 empty mongodb 集合进行批量插入时出现以下错误。

pymongo.errors.DuplicateKeyError: E11000 重复键错误索引: cmdDistros.locDistro.$id 复制键:: ObjectId('51dac9d0c74cd81acd85c0fd')

我在创建任何文档时都没有指定 _id,所以 mongodb 应该正确创建唯一索引吗?这是我使用的代码:

#Populate database with uniform distribution
            entries = []
            for coor in freeIndices:
                for theta in range(360):
                    entry = "x" : coor[0], "y" : coor[1], "heading" : theta
                    for i in range(numData):
                            entry["data" + str(i)] = 1./numData
                    entries.append(entry)
            print "Entries created, loading into database..."

            locDistro.insert(entries)

从 mongoDB 手中夺走命运,我尝试使用以下方法创建自己的索引:

#Populate database with uniform distribution
            entries = []
            idNum = 0
            for coor in freeIndices:
                for theta in range(360):
                    print idNum
                    entry = "_id" : idNum, "x" : coor[0], "y" : coor[1], "heading" : theta
                    idNum += 1
                    for i in range(numData):
                            entry["data" + str(i)] = 1./numData
                    entries.append(entry)
            print "Entries created, loading into database..."

            locDistro.insert(entries, manipulate = False)

打印语句显示文档创建时的每个 idnum,它们都是唯一的,并且按预期递增。但是在插入时,我收到了错误:

pymongo.errors.DuplicateKeyError: E11000 重复键错误索引: cmdDistros.locDistro.$id 复制密钥: : 0

只有一个文档被插入到我的数据库中。

我完全被难住了,有人知道为什么会发生这种情况吗?

【问题讨论】:

我不知道发生了什么,但是问题已经设法自行解决了...我只是一遍又一遍地运行代码,它就可以正常工作....奇怪..如果有人有一个解释我仍然想知道以防它再次发生......顺便说一下,entry.append 行是一个错字,实际位置与它上面的 for 对齐。 集合中是否定义了其他索引? 无。只是_id。我想使用 ensure_index 在 x y 和标题上创建索引,但它们不是唯一的,所以我不确定这是否可行。无论如何,此时只有 _id 被索引。 这两个选项现在有效吗? _id是驱动创建的,_id是自己创建的。 驱动创建的_id现在可以工作了,我自己的_id没有尝试过创建,经验让我在知道可以工作后不敢再碰代码。 【参考方案1】:

您需要了解您的条目列表有一堆对 one 条目字典的引用。因此,当 PyMongo 设置条目[0]['_id'] 时,所有其他条目都会获得相同的 _id。 (事实上​​,PyMongo 将遍历列表设置每个条目的 _id,因此所有条目的末尾都会有 final _id。)快速解决方法是:

entries.append(entry.copy())

这只是一个浅拷贝,但在您分享的代码中,我相信这足以解决您的问题。

【讨论】:

每个循环都在创建条目,它们如何指向同一个对象?我认为这不是正确的答案 我也被 pymongo 的insert_one 这种奇怪的行为所困扰。我听说过copy 方法和del obj['_id'] 方法。我仍然没有得到复制方法。尽管对象不同,我是否也必须为我插入的每个对象制作一个副本? 当插入具有相同引用的多个对象时,此答案也适用于 NodeJS 哈哈。谢谢 这解决了我的问题,但我仍然不清楚为什么会这样。在附加到条目之前,条目在每次迭代时被初始化。发生了一些奇怪的事情【参考方案2】:

删除密钥"_id"

for i in xrange(2): 
    doc['i'] = i 
    if '_id' in doc: 
        del doc['_id'] 
    collection.insert(doc)

或者手动新建一个:

from bson.objectid import ObjectId

for i in xrange(2): 
    doc['i'] = i 
    doc['_id'] = ObjectId() 
    collection.insert(doc)

Getting "err" : "E11000 duplicate key error when inserting into mongo using the Java driver

【讨论】:

【参考方案3】:

我在使用 insert_one()insert_many() 时遇到了同样的错误

我的解决方案是使用update_one()upsert=True

  doc = a: 1, b:2, x:xx:"hello",yy:"world"
  db.collection.update_one(doc,'$set':doc,upsert=True)

这对我有用:-)

【讨论】:

这个很不错。为我工作。【参考方案4】:

确保在每次插入后清除变量“条目”。

问题是 PyMongo 会在文档中注入一个 _id 字段,如果 _id 字段不存在,则在插入之前(_id总是在客户端生成)。这意味着第一次通过循环 _id 是由 insert 方法添加的。由于 'entries' 是在外部定义的,因此每次后续循环都使用相同的 _id 值。

清除循环语句顶部的 dict 变量。

从字典中移除 _id。例如:

del my_dict['_id'] 

【讨论】:

【参考方案5】:

解决方案:在循环内声明 dict() 项,然后填充并插入它。 我在使用 pymongoinsert_one() 时遇到了类似的问题。我通过在循环中声明 dict() 项解决了我的问题。 这是您的代码的工作版本:

#Populate database with uniform distribution
            entries = []
            for coor in freeIndices:
                for theta in range(360):
                    entry = dict()
                    entry['x'] = coor[0]
                    entry['y'] = coor[1]
                    entry['heading'] = theta
             
                    for i in range(numData):
                            entry['data' + str(i)] = 1./numData
                    entries.append(entry)
            print "Entries created, loading into database..."

            locDistro.insert(entries)

【讨论】:

以上是关于MongoDB插入引发重复键错误的主要内容,如果未能解决你的问题,请参考以下文章

MongoDb c# .net Save 抛出重复键异常

临时表异常 - e11000 重复键错误

如何避免mongodb中的重复键错误收集

mongodb mongoose中的重复键错误索引

MongoDB E11000 重复键错误

Mongodb重复键错误收集dup key: null