如何使用insert_many

时间:2017-06-30 03:48:06

标签: python mongodb pymongo

在将insert_many与pymongo一起使用时,我需要忽略重复插入,其中重复项基于索引。我已经在stackoverflow上看到了这个问题,但我还没有看到有用的答案。

这是我的代码段:

try:
    results = mongo_connection[db][collection].insert_many(documents, ordered=False, bypass_document_validation=True)
except pymongo.errors.BulkWriteError as e:
    logger.error(e)

我希望insert_many忽略重复项而不抛出异常(填满我的错误日志)。或者,我可以使用单独的异常处理程序,以便我可以忽略错误。我想念" w = 0" ...

由于

3 个答案:

答案 0 :(得分:9)

您可以通过检查BulkWriteError生成的错误来解决此问题。这实际上是一个"对象"它有几个属性。有趣的部分在details

import pymongo
from bson.json_util import dumps
from pymongo import MongoClient
client = MongoClient()
db = client.test

collection = db.duptest

docs = [{ '_id': 1 }, { '_id': 1 },{ '_id': 2 }]


try:
  result = collection.insert_many(docs,ordered=False)

except pymongo.errors.BulkWriteError as e:
  print e.details['writeErrors']

首次运行时,会在e.details['writeErrors']下显示错误列表:

[
  { 
    'index': 1,
    'code': 11000, 
    'errmsg': u'E11000 duplicate key error collection: test.duptest index: _id_ dup key: { : 1 }', 
    'op': {'_id': 1}
  }
]

第二次运行时,您会看到三个错误,因为所有项目都存在:

[
  {
    "index": 0,
    "code": 11000,
    "errmsg": "E11000 duplicate key error collection: test.duptest index: _id_ dup key: { : 1 }", 
    "op": {"_id": 1}
   }, 
   {
     "index": 1,
     "code": 11000,
     "errmsg": "E11000 duplicate key error collection: test.duptest index: _id_ dup key: { : 1 }",
     "op": {"_id": 1}
   },
   {
     "index": 2,
     "code": 11000,
     "errmsg": "E11000 duplicate key error collection: test.duptest index: _id_ dup key: { : 2 }",
     "op": {"_id": 2}
   }
]

所以你需要做的就是过滤数组以查找"code": 11000的条目,然后只有"恐慌"当其他东西在那里时

panic = filter(lambda x: x['code'] != 11000, e.details['writeErrors'])

if len(panic) > 0:
  print "really panic"

这为您提供了一种忽略重复键错误的机制,但当然要注意实际上存在问题的内容。

答案 1 :(得分:2)

为Neil的解决方案添加更多内容。

具有'ordered = False,bypass_document_validation = True'参数允许即使在重复异常的情况下也可以进行新的挂起插入。

from pymongo import MongoClient, errors

DB_CLIENT = MongoClient()
MY_DB = DB_CLIENT['my_db']
TEST_COLL = MY_DB.dup_test_coll

doc_list = [
    {
        "_id": "82aced0eeab2467c93d04a9f72bf91e1",
        "name": "shakeel"
    },
    {
        "_id": "82aced0eeab2467c93d04a9f72bf91e1",  # duplicate error: 11000
        "name": "shakeel"
    },
    {
        "_id": "fab9816677774ca6ab6d86fc7b40dc62",  # this new doc gets inserted
        "name": "abc"
    }
]

try:
    # inserts new documents even on error
    TEST_COLL.insert_many(doc_list, ordered=False, bypass_document_validation=True)
except errors.BulkWriteError as e:
    print(f"Articles bulk insertion error {e}")

    panic_list = list(filter(lambda x: x['code'] != 11000, e.details['writeErrors']))
    if len(panic_list) > 0:
        print(f"these are not duplicate errors {panic_list}")

由于我们正在谈论重复项,因此也值得检查this solution

答案 2 :(得分:0)

正确的解决方案是使用 w=0 的 WriteConcern:

import pymongo
from pymongo.write_concern import WriteConcern


mongodb_connection[db][collection].with_options(write_concern=WriteConcern(w=0)).insert_many(messages)