How do I copy a collection from one database to an

2019-07-29 04:26发布

问题:

I am trying to copy a MongoDB collection from one database to another database on the same server.

from pymongo import MongoClient
client = MongoClient()
client.db1.coll1.insert({'content':'hello world'})

I would like to copy db1.coll to db2.coll2 on the same server.

I tried to follow the "copy and move" approach described in How to copy a collection from one database to another in MongoDB but this doesn't work in pymongo.

In particular, the copy step

client.db1.coll1.aggregate([{'$out':'coll2'}])

works but then I get an error when trying to perform the move:

>>> client.admin.command({'renameCollection':'db1.coll2', 'to':'db2.coll2'})
OperationFailure: no such command: 'to', bad cmd: '{ to: "db2.coll2", renameCollection: "db1.coll2" }

回答1:

After a lot of confusion and soul searching, I was eventually able to track this down to dicts in Python being unordered (at least prior to 3.6) and MongoDB expecting an ordered BSON dictionary.

Using an OrderedDict as pointed out in How to get ordered dictionaries in pymongo? resolve this:

>>> from collections import OrderedDict
>>> client.admin.command(
    OrderedDict([('renameCollection','db1.coll2'), ('to','db2.coll2')]))
{u'ok': 1.0}

Another alternative is to use a SON object from BSON.

>>> import bson
>>> client.admin.command(
    bson.son.SON([('renameCollection','db1.coll2'), ('to','db2.coll2')]))
{u'ok': 1.0}

Another approach is to pass Javascript to MongoDB using the eval() function:

>>> client.admin.eval(
    "db.runCommand({'renameCollection':'db1.coll2', 'to':'db2.coll2'})") 
{u'ok': 1.0}

I find the raw Javascript version less pythonic but is useful because it allowed me to test the MongoDB functionality without having to fire up a MongoDB shell. I also haven't seen it mentioned much on PyMongo StackOverflow questions so thought it's worth including here.