如何使用 PyMongo 在重复键错误后继续插入

Posted

技术标签:

【中文标题】如何使用 PyMongo 在重复键错误后继续插入【英文标题】:How to continue insertion after duplicate key error using PyMongo 【发布时间】:2016-07-05 03:22:48 【问题描述】:

如果我需要在MongoDB中插入一个尚不存在的文档

db_stock.update_one(document, '$set': document, upsert=True)

.将完成这项工作(如果我错了,请随时纠正我)

但是,如果我有一个文档列表并且想要将它们全部插入,那么最好的方法是什么?

这个question 有一个单记录版本,但我需要它的一个整体版本,所以它是不同的。

让我重新提出我的问题。我有数以百万计的文档,其中很少有可以存储的。如何在几秒钟内而不是几分钟/几小时内将剩余的存储在 MongoDB 中?

【问题讨论】:

不幸的是,没有其他方法可以迭代文档并使用 update_one。我在考虑批量操作,但要使用 bulk.find.upsert 你需要先在 db 中有这个文档。 好的。可以批量删除列表中的文档,然后批量插入吗? 如果您将完整的集合放入列表 - 那么您可以删除集合并插入,或通过已知 ID(检索到的)删除并使用 insert_many 重新插入。 【参考方案1】:

您需要使用insert_many 方法并将ordered 选项设置为False

db_stock.insert_many(<list of documents>)

ordered 选项文档中所述:

有序(可选):如果为 True(默认),文档将按提供的顺序连续插入服务器。如果发生错误,所有剩余的插入都将中止。如果为 False,文档将在服务器上以任意顺序插入,可能是并行的,并且将尝试所有文档插入。

这意味着即使存在重复键错误,插入也会继续。

演示:

>>> c.insert_many(['_id': 2, '_id': 3])
<pymongo.results.InsertManyResult object at 0x7f5ca669ef30>
>>> list(c.find())
['_id': 2, '_id': 3]
>>> try:
...     c.insert_many(['_id': 2, '_id': 3, '_id': 4, '_id': 5], ordered=False)
... except pymongo.errors.BulkWriteError:
...     list(c.find())
... 
['_id': 2, '_id': 3, '_id': 4, '_id': 5]

您可以看到带有_id 4 的文档,其中5 个被插入到集合中。


值得注意的是,这也可以在 shell 中使用insertMany 方法实现。您只需将未记录的选项 ordered 设置为 false

db.collection.insertMany(
    [ 
         '_id': 2 , 
         '_id': 3 ,
         '_id': 4 , 
         '_id': 5 
    ],
     'ordered': false 
)

【讨论】:

@ORA600 只是为了明确区分,使用“upserts”(即使使用 bulk 操作,并且仍然是当前 pymongo 的旧界面)意味着您仍在“查找”之前的数据决定是否“插入”。 “查找”的本质意味着您永远不会得到重复,然而它自然会带来“成本”。因此,使用ordered=False 对“insert_many”的建议(仍然可以对“bulk”做同样的事情)没有那种“查找”开销。因此它是“最快的”,这就是您所要求的。【参考方案2】:

使用 bulkWrite 你可以做到这一点,虽然我不确定它的 pymongo 命令是什么,这里是直接的 mongodb 查询:

db.products.insert([
   _id: 11, item: "pencil", qty: 50, type: "no.2" ,
   item: "pen", qty: 20 ,
   item: "eraser", qty: 25 
])

【讨论】:

这不是这个特定问题的答案,因为它声明“批量 UPSERT” 他的问题在标题和问题正文中都显示 insert "en masse" 表示批量 :-)

以上是关于如何使用 PyMongo 在重复键错误后继续插入的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB插入引发重复键错误

如何使用 insert_many 安全地忽略重复的键错误

在pymongo的update_one()中出现重复键错误

插入后如何在 PyMongo 中获取对象 ID?

Codeigniter:当我插入数据时出现重复键错误,我该如何处理这个错误?

MongoDB---如何避免插入重复数据(pymongo)