59

I want to clone a MongoDB collection and save it on the same server with a different name. So for example right now I have the following collections: demo1.categories, demo1.users and demo2.users.

I want to have a "demo2.categories" which is identical to "demo1.categories". (It just has a different name.)

Naman
  • 27,789
  • 26
  • 218
  • 353
Daryna
  • 749
  • 1
  • 7
  • 11
  • The accepted answer was arguably the best method back in 2012, but now db.cloneCollection() is a good & better method to get a solution. – Prakash Harvani Sep 19 '20 at 05:03

8 Answers8

82

Yet again the MongoDB documentation comes to the rescue

assuming that the collection actually is named "demo1.categories":

db.demo1.categories.find().forEach( function(x){db.demo2.categories.insert(x)} );
lhagemann
  • 1,268
  • 11
  • 13
  • 55
    As of 2.1+ you can do db.demo1.copyTo("demo2"); – Remon van Vliet Jan 20 '12 at 13:09
  • 15
    `copyTo` blocks all other operations in mongod instance – r92 Jun 02 '14 at 08:32
  • 3
    in 2.0.4 this way converted all my collection's int values into double values... So, this method will not guarantee 100% equality... – Tutankhamen Jul 25 '14 at 21:35
  • 1
    Issue with copyTo is that it requires the "anyAction" role on "anyResource" , which isn't recommended to be given to all users. (and might not be granted to you if you're in a large organization) Apparently, `cloneCollection` is a better option since all it needs are read\write permissions. Of course, the above answer also works. – arviman Mar 02 '15 at 08:51
  • These things not worked for me. It says Message.find(...).forEach is not a function – Iron_Man Jan 05 '18 at 11:25
  • Actually I want it to do automatically with the help of cron job on nodejs. So whenever cron job hits the command, then simply copy the collection and paste to the new collection – Iron_Man Jan 05 '18 at 11:27
31

The most simple & efficient way is by using copyTo(), so you can use:

db.source.copyTo("target"); 

& if "target" doesn't exist, it will be created

-- Update --

According to CopyTo Documentation, Because copyTo() uses eval internally, the copy operations will block all other operations on the mongod instance. So it shouldn't be used on production environment.

-- Update --

Because CopyTo() uses eval() internally & eval() is deprecated since version 3.0, so CopyTo() is also deprecated since version 3.0.

AbdelHady
  • 9,334
  • 8
  • 56
  • 83
30

This is the fastest way to clone your collection:

mongoexport -d db_name -c src_collection | mongoimport -d db_name -c dst_collection --drop

it will clone src_collection in db_name to dst_collection. Or you can do it in two steps on bson level:

mongodump -d db_name -c src_collection
mongorestore --drop -d db_name -c dst_collection ./dump/db_name/src_collection.bson
Tutankhamen
  • 3,532
  • 1
  • 30
  • 38
  • 4
    This way isn't just easiest, but also guarantees you 100% identity on binary level, but find() and insert() way doesn't. For example, it converts all your integer records into numerics, etc – Tutankhamen Oct 23 '14 at 17:07
  • 2
    for authentication, and to connect to remote server, add following args to both sides of the pipe- `--host="whatever" --port="27017" --username="myuser" --password="mypass" --authenticationDatabase="admin"` – Kip Dec 12 '19 at 22:40
22

The fastest option is

db.myoriginal.aggregate([ { $out: "mycopy" } ])
tejzpr
  • 945
  • 8
  • 19
  • I'm using https://github.com/caolan/async in my node.js application and this didn't work for the mongodb node.js driver - I'm now using the `find().forEach(....)` solution - still upvoted this because it works in the console – Matthias Herrmann Dec 27 '17 at 10:00
  • Yeah, this is the fastest way for copying from one collection into another db.myoriginal_collection.aggregate([{$match: { id: "id" }},{ $out: "myoriginal_duplicate_collection" } ]) – Karthik Samyak Apr 27 '18 at 09:02
2

there already has a command for this.

Copy a single collection from one server to another. http://www.mongodb.org/display/DOCS/cloneCollection+Command

kerwin
  • 941
  • 2
  • 12
  • 22
  • 8
    You are correct that this command will allow you to copy from one server to another. However, the original question refers to the same server. As the documentation indicates, you will lose your collection if you attempt to use the cloneCollection command for the original question's goal – Andy Davis Jul 19 '12 at 18:27
2

If you're concerned about speed then I found that by using aggregate with $project and $out to be a 100 times faster, not sure if there are restrictions though, but you would have to create a set of fields that you'd want to copy For example:

// Set of fields in the categories collection
var setOfFields = {field1:1, field2:1.......}
db.demo1.categories.aggregate([{ "$project": setOfFields},{ $out: "demo2.categories"}]);

This copies (projects) the selected set of fields for all documents from demo1.categories to demo2.categories

Elangovan
  • 3,469
  • 4
  • 31
  • 38
Chenna V
  • 10,185
  • 11
  • 77
  • 104
0

Don't use db.cloneCollection() method, it is depreciated from the current version 4.2 instead try to use mongoexport.

depreciated collection method

Ajay
  • 35
  • 1
  • 6
-4

In the mongo console, you can do the following as well, where db_host is the machine where db_host has the db with the collection that you want to clone.

use db.cloneCollection(, )

  • Sorry there was some formatting issues, it should be use db_name then db.cloneCollection(collection_name, db_host) –  Aug 09 '12 at 15:34
  • 1
    and reverse db_host and collection name i.e. db.cloneCollection(host, collection) –  Aug 09 '12 at 15:41
  • that doesn't work: { "ok" : 0, "errmsg" : "can't cloneCollection from self" } – Dominik Goltermann Jun 25 '13 at 15:06
  • check mongo docu: http://docs.mongodb.org/manual/reference/method/db.cloneCollection/ The collection in the MongoDB instance that you want to copy. db.cloneCollection() will only copy the collection with this name ** from database of the same name as the current database ** the remote MongoDB instance. If you want to copy a collection from a different database name you must use the cloneCollection directly. – Markus Schmidberger Jun 27 '13 at 14:05