我已阅读到,当我使用pymongo的upsert且不提供“ _id”时,upsert将尝试生成新的ID,这将导致操作失败。这是真的?以及如何在不使用“ _id”的情况下向上插入?
这是我使用pymongo的replace_one:
db['dataitemdetails'].replace_one({'asset_Id':tdata['asset_id'],'period_type':tdata['period_type'],'detail_id':tdata['detail_id'], 'currencycode':tdata['currencycode'],'dataitem_Id':tdata['dataitem_id'],'period_end':tdata['period_end'], 'scenario_id':tdata['scenario_id'],}, tdata, upsert=True)
我已经创建了一个复合索引,并使用搜索条件将其设置为唯一,这样,在集合中,如果搜索到的内容,我搜索的内容将始终唯一。
,并与replace_one我收到此错误:
pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: finance.dataitemdetails index: asset_id_1_dataitem_id_1_detail_id_1_period_type_1_scenario_id_1_currencycode_1_period_end_1 dup key: { : 19, : 1211, : 0, : "Month", : 1, : "RC", : new Date(949276800000) }
这是我用相同过滤器查询的查询,它返回1个文档。
> db.dataitemdetails.find({'asset_id':19,'dataitem_id':1211,'detail_id':0,'period_type':'Month','currencycode':'RC','period_end':new Date(949276800000)})
{ "_id" : ObjectId("5c7721c17314e53a85be7e89"), "Value" : "USD", "period_end" : ISODate("2000-01-31T00:00:00Z"), "currencycode" : "RC", "scenario_id" : 1, "dataitem_id" : 1211, "period_type" : "Month", "detail_id" : 0, "asset_id" : 19 }
我坚持不知道要尝试什么以及如何解决它。
完整的错误消息:
Traceback (most recent call last):
File "./periodic_update.sh", line 307, in <module>
db['dataitemdetails'].replace_one({'asset_Id':tdata['asset_id'],'period_type':tdata['period_type'],'detail_id':tdata['detail_id'], 'currencycode':tdata['currencycode'],'dataitem_Id':tdata['dataitem_id'],'period_end':tdata['period_end'], 'scenario_id':tdata['scenario_id'],}, tdata, upsert=True)
File "/usr/local/lib64/python3.7/site-packages/pymongo/collection.py", line 925, in replace_one
collation=collation, session=session),
File "/usr/local/lib64/python3.7/site-packages/pymongo/collection.py", line 851, in _update_retryable
_update, session)
File "/usr/local/lib64/python3.7/site-packages/pymongo/mongo_client.py", line 1248, in _retryable_write
return self._retry_with_session(retryable, func, s, None)
File "/usr/local/lib64/python3.7/site-packages/pymongo/mongo_client.py", line 1201, in _retry_with_session
return func(session, sock_info, retryable)
File "/usr/local/lib64/python3.7/site-packages/pymongo/collection.py", line 847, in _update
retryable_write=retryable_write)
File "/usr/local/lib64/python3.7/site-packages/pymongo/collection.py", line 818, in _update
_check_write_command_response(result)
File "/usr/local/lib64/python3.7/site-packages/pymongo/helpers.py", line 217, in _check_write_command_response
_raise_last_write_error(write_errors)
File "/usr/local/lib64/python3.7/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: finance.dataitemdetails index: asset_id_1_dataitem_id_1_detail_id_1_period_type_1_scenario_id_1_currencycode_1_period_end_1 dup key: { : 19, : 1211, : 0, : "Month", : 1, : "RC", : new Date(949276800000) }
```
Find in Mongodb console returned only 1 document
```
>db.dataitemdetails.find({'asset_id':19,'dataitem_id':1211,'detail_id':0,'period_type':'Month','currencycode':'RC','period_end':new Date(949276800000)})
{ "_id" : ObjectId("5c7721c17314e53a85be7e89"), "Value" : "USD", "period_end" : ISODate("2000-01-31T00:00:00Z"), "currencycode" : "RC", "scenario_id" : 1, "dataitem_id" : 1211, "period_type" : "Month", "detail_id" : 0, "asset_id" : 19 }
>
```
Here is my replace one query in the mongo console instead of pymongo:
```
> db.dataitemdetails.replaceOne({'asset_id':19,'dataitem_id':1211,'detail_id':0,'period_type':'Month','currencycode':'RC','period_end':new Date(949276800000)} ,{'asset_id':19,'dataitem_id':1211,'detail_id':0,'period_type':'Month','currencycode':'RC','period_end':new Date(949276800000), 'Value':'USD'}, upsert = true)
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
>
```
some other notes:
If I remove the compound index, the error message would go away, but I would end up with duplicate documents that are the same.
I tried to drop the collection, database and it would end up the same.
答案 0 :(得分:1)
我发现了问题:
在这行代码中:
db['dataitemdetails'].replace_one({'asset_Id':tdata['asset_id'],'period_type':tdata['period_type'],'detail_id':tdata['detail_id'], 'currencycode':tdata['currencycode'],'dataitem_Id':tdata['dataitem_id'],'period_end':tdata['period_end'], 'scenario_id':tdata['scenario_id'],}, tdata, upsert=True)
我的过滤器有误。
其中asset_Id应该为asset_id,而dataitem_Id应该为dataitem_id。
因此找不到匹配项,但是在插入重复的键错误时出现。
答案 1 :(得分:0)
您正在告诉mongodb替换一个文档。您的过滤器很可能会返回多个文档。
使用带有相同过滤器的find
并找出一个将始终返回一个文档的过滤器。在大多数情况下,只要正确布置架构,仅使用id
就足以返回一个文档。
答案 2 :(得分:0)
要回答第一个问题,
如果您不提供upsert = true的_id字段值,MongoDB将生成一个新的ID
出现重复键错误的原因是,您没有在过滤条件中使用period
字段。