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" }
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.