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() 项,然后填充并插入它。 我在使用 pymongo 的 insert_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插入引发重复键错误的主要内容,如果未能解决你的问题,请参考以下文章