【问题标题】:MongoDB insert raises duplicate key errorMongoDB插入引发重复键错误
【发布时间】: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没有尝试过创建,经验让我在知道可以工作后不敢再碰代码。

标签: python mongodb pymongo database


【解决方案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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-21
        • 2020-09-29
        • 2014-04-16
        • 1970-01-01
        相关资源
        最近更新 更多