我正在尝试使用pymongo将对象保存到mongodb。我的第一个对象没有问题,但是当尝试保存第二个对象时,我得到了pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: km_tracker.entries index: _id_ dup key: { : ObjectId('5b8ce80ebb822e06c8ecf1c7') }
我的保存功能:
def save_entries(entries):
entries['save_date'] = str(datetime.datetime.now())
db.entries.insert_one(entries)
回溯:
Traceback (most recent call last):
File "app.py", line 182, in <module>
main();
File "app.py", line 22, in main
new_entry()
File "app.py", line 77, in new_entry
review_information(entries)
File "app.py", line 178, in review_information
save_entries(entries)
File "app.py", line 93, in save_entries
db.entries.insert_one(entries)
File "C:\Users\someuser\AppData\Local\Programs\Python\Python37\lib\site-packages\pymongo\collection.py", line 693, in insert_one
session=session),
File "C:\Users\someuser\AppData\Local\Programs\Python\Python37\lib\site-packages\pymongo\collection.py", line 607, in _insert
bypass_doc_val, session)
File "C:\Users\someuser\AppData\Local\Programs\Python\Python37\lib\site-packages\pymongo\collection.py", line 595, in _insert_one
acknowledged, _insert_command, session)
File "C:\Users\someuser\AppData\Local\Programs\Python\Python37\lib\site-packages\pymongo\mongo_client.py", line 1243, in _retryable_write
return self._retry_with_session(retryable, func, s, None)
File "C:\Users\someuser\AppData\Local\Programs\Python\Python37\lib\site-packages\pymongo\mongo_client.py", line 1196, in _retry_with_session
return func(session, sock_info, retryable)
File "C:\Users\someuser\AppData\Local\Programs\Python\Python37\lib\site-packages\pymongo\collection.py", line 592, in _insert_command
_check_write_command_response(result)
File "C:\Users\someuser\AppData\Local\Programs\Python\Python37\lib\site-packages\pymongo\helpers.py", line 217, in _check_write_command_response
_raise_last_write_error(write_errors)
File "C:\Users\someuser\AppData\Local\Programs\Python\Python37\lib\site-packages\pymongo\helpers.py", line 198, in _raise_last_write_error
raise DuplicateKeyError(error.get("errmsg"), 11000, error)
pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: km_tracker.entries index: _id_ dup key: { : ObjectId('5b8ce6adbb822e40d431d444') }
已成功保存到数据库中的第一个对象:
{
"_id" : ObjectId("5b8ce6adbb822e40d431d444"),
"reg_number" : "dfg",
"date" : "dfg",
"b_meter_indication" : "dfg",
"end_meter_indication" : "dfg",
"trip" : "dfg",
"start_address" : "dfg",
"stop_address" : "dfg",
"reason" : "dfg",
"driver" : "dfg",
"other" : "dfg",
"save_date" : "2018-09-03 09:45:49.340871"
}
第二个对象,由于重复键而未保存:
{'_id': ObjectId('5b8ce6adbb822e40d431d444'),
'b_meter_indication': 'rty',
'date': 'rty',
'driver': 'rty',
'end_meter_indication': 'rty',
'other': 'rty',
'reason': 'rty',
'reg_number': 'try',
'save_date': '2018-09-03 09:46:02.246101',
'start_address': 'rty',
'stop_address': 'rty',
'trip': 'rty'
}
由于我没有明确定义_id
的值,而是让pymongo为我完成此操作,所以我不明白为什么它将_id
的先前值分配给当前对象。出于某种原因,pymongo是否可能会认为第二个对象与第一个对象相同,从而赋予它相同的_id
值?
Python版本:3.7.0 Mongodb版本4.0 PyMongo版本:3.7.1
编辑:使用save_entries()函数添加的功能
def edit_entry(entries):
print("Editing: {}".format(entries))
entry = input()
return entry
def review_information(entries):
print("Do you wish to edit something? (y/n)")
while edit != False or edit != False:
edit = input()
if edit == "Y" or edit == "y":
edit_entry(entries)
elif edit == "N" or edit == "n":
break
else:
print("Please provide a valid input")
continue
save_entries(entries)
答案 0 :(得分:1)
我也有同样的问题,但是现在我解决了。
就我而言,我在for循环中创建了一个新字典。首先在循环判断条件下,如果日期是我所需要的,我将insert_one制作到MongoDB数据库,但是Pymongo认为即使文件中的内容完全不同,它也是同一个对象,因为dict具有相同的内存ID,所以它没有。 t创建一个新的“ _id”。所以我需要将dict从循环位置放到if位置。
for itemin items:
i = 1
while i < len(item['a']):
if (item['a'][i-1]['date'] < item['a'][i]['date']:
temp= {} #this one
...
db.collection.insert_one(temp)
i +=1
答案 1 :(得分:0)
我没有明确定义_id的值,而是让pymongo为我完成此操作
这是因为,当使用insert_one(),insert_many()或bulk_write()将文档插入到MongoDB中时,该文档不包含_id
字段,{{3 }}会自动为您添加一个,并设置为ObjectId
的实例。
另请参阅PyMongo
第一个对象没有问题,但是尝试保存第二个对象时出现pymongo.errors.DuplicateKeyError
Python并没有按值显式传递和按引用语义传递,而是按名称传递值。列表和字典是可变对象,数字,字符串和元组是不可变对象。
在您的情况下,实际上是将相同的entries
对象传递给save_entries()
函数。 PyMongo insert_one()
通过添加_id
字段修改了对象,然后您尝试再次保存。但是,第二次保存已经包含_id
字段,从而导致重复错误。
处理这种情况的方法很少:
save_entries()
之前显式FAQ: Why does PyMongo add an _id field to all of my documents?对象。 _id
后,从对象中删除save_entries()
键。即del entries["_id"]
。