python - Mongodb Replace_one() with upsert = true 抛出重复键错误

标签 python mongodb pymongo

我读到,当我使用 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.

最佳答案

我发现了问题:

在这行代码中:

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。

因此未找到匹配项,但在插入重复键时会引发错误。

关于python - Mongodb Replace_one() with upsert = true 抛出重复键错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54917622/

相关文章:

Python-撤消标准输出重定向

python - 将列表环绕为切片操作

javascript - 刷新 $http Promise 返回的数据

python - pymongo.errors.InvalidOperation : cannot set options after executing query

python - 如何使用 pymongo 删除一个集合?

python - 使用 pandas 取消嵌套数组列

python - 如何使用 Tableau 或 Excel 将数据时间转换为秒数

node.js - 使用管道中数组中的对象值执行 $lookup

regex - 使用 PHP 进行整数值的 MongoDB 正则表达式搜索

mongodb - 将 ISODate 字符串转换为 mongoDB 原生 ISODate 数据类型