Reputation: 106
I am trying to call the mongodb cloneCollection command from ruby. Based on the first question at https://github.com/mongodb/mongo-ruby-driver/wiki/FAQ I made this test script:
require "mongo"
include Mongo
db = MongoClient.new("localhost", 27017).db("test")
coll = "users2"
cmd = {}
cmd['cloneCollection'] = coll
cmd['from'] = "test.example.com:27017"
db.command(cmd)
However, instead of cloning the users2 collection, it creates an empty database with the same name. Cannot figure out what I'm doing wrong. Any ideas? Thanks!
Upvotes: 1
Views: 596
Reputation: 32374
After being surprised that Mongo::DB
does not have a cloneCollection
method, and reading @Gary Murakami's excellent answer above, I wrote this piece of monkey patch that I though may be useful to others:
class Mongo::DB
def cloneCollection(remote_host, collection_name)
cmd = BSON::OrderedHash.new
cmd['cloneCollection'] = name + "." + collection_name
cmd['from'] = remote_host
self.command(cmd)
end
end
Just drop it anywhere in your source file to get a Mongo::DB.cloneCollection
implementation.
Upvotes: 0
Reputation: 3402
The following Ruby program is a self-contained working example that should answer your question, complete with startup of source and destination mongod servers.
It appears that the arg to cloneCollection must be a fully qualified name, e.g., "test.users" for the "users" collection in the "test" database.
require "mongo"
# startup source and destination mongod servers
source = { 'port' => 27018, 'dbpath' => 'data27018' }
dest = { 'port' => 27019, 'dbpath' => 'data27019' }
[ source, dest ].each do |server|
dbpath = server['dbpath']
system("rm -fr #{dbpath} && mkdir #{dbpath} && mongod --port #{server['port']} --dbpath #{dbpath} &")
end
sleep 10 # delay for mongod startup
db_name = 'test'
coll_name = 'users'
db_coll_name = "#{db_name}.#{coll_name}"
# create source collection
db = Mongo::MongoClient.new("localhost", source['port']).db(db_name)
coll = db[coll_name]
coll.insert({'name' => 'Gary'})
# cloneCollection from source to dest
db = Mongo::MongoClient.new("localhost", dest['port']).db(db_name)
cmd = BSON::OrderedHash.new
cmd['cloneCollection'] = db_coll_name
cmd['from'] = "localhost:#{source['port']}"
db.command(cmd)
# verify cloneCollection
p db[coll_name].find.to_a
# kill mongod servers
pids = `pgrep mongod`.split(/\n/).sort.slice(-2,2)
system("kill #{pids.join(' ')}")
Please let me know if you have any further questions.
Upvotes: 2