【问题标题】:How to continue insertion after duplicate key error using PyMongo如何使用 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 重新插入。

标签: python mongodb mongodb-query pymongo


【解决方案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" 表示批量 :-)
猜你喜欢
  • 1970-01-01
  • 2020-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多