将记录从一个集合移动到另一个集合PyMongo

时间:2017-12-04 22:04:06

标签: python database mongodb nosql pymongo

将多个记录从一个集合移动到另一个集合的正确方法是什么。我遇到了其他几个SO帖子,例如this,它们实现了相同的目标,但没有一个有python实现。

#Taking a number of records from one database and returning the cursor
cursor_excess_new = db.test_collection_new.find().sort([("_id", 1)]).limit(excess_num)


# db.test.insert_many(doc for doc in cursor_excess_new).inserted_ids


# Iterating cursor and Trying to write to another database
# for doc in cursor_excess_new:
#     db.test_collection_old.insert_one(doc)
result = db.test_collection_old.bulk_write([
    for doc in cursor_excess_new:
        InsertMany(doc for each doc in cur)
        pprint(doc)
])

如果我使用insert_many,则会收到以下错误:pymongo.errors.OperationFailure: Writes to config servers must have batch size of 1, found 10

bulk_write在for循环开始时给出了语法错误。

在pymongo中将记录从一个集合转移到另一个集合的最佳实践和正确方法是什么,以便它是原子的?

2 个答案:

答案 0 :(得分:1)

Collection.bulk_write接受一个可迭代的查询操作作为参数。

pymongopymongo.operations.InsertOne次操作,而不是 InsertMany

根据您的情况,您可以为源集合中的每个文档构建InsertOne操作列表。然后使用构建的操作列表在目标上执行bulk_write。

from pymongo import InsertOne
...
cursor_excess_new = (
    db.test_collection_new
      .find()
      .sort([("_id", 1)])
      .limit(excess_num)
)

queries = [InsertOne(doc) for doc in cursor_excess_new]
db.test_collection_old.bulk_write(queries)

答案 1 :(得分:0)

您不需要“ for循环”。

   myList=list(collection1.find({}))
   collection2.insert_many(myList)
   collection1.delete_many({})

如果需要过滤,可以使用以下代码:

   myList=list(collection1.find({'status':10}))
   collection2.insert_many(myList)
   collection1.delete_many({'status':10})

但是要小心,因为它不能成功移动,因此您需要控制交易。如果要使用以下代码,则应考虑MongoDb不应独立运行,而需要激活Replication并拥有另一个实例。

  with myClient.start_session() as mySession:
      with mySession.start_transaction():
          ...yourcode...

最后,上述代码具有成功移动(插入和删除)的保证,但是交易不在您手中,您无法获得此交易的结果,因此可以使用以下代码来控制这两个移动和交易:

  with myClient.start_session() as mySession:
      mySession.start_transaction()
      try:
          ...yourcode...
          mySession.commit_transaction()
          print("Done")
      except Exception as e:
          mySession.abort_transaction()
          print("Failed",e)