66

Ok, I suppose that this is a silly question and probably has a simple answer.

How can I duplicate a document in MongoDB, changing the _id of the new one?

Imaging that you have the original document:

> var orig = db.MyCollection.findOne({_id: 'hi'})

And now I want another document in the collection with _id 'bye'.

José María Ruiz
  • 859
  • 1
  • 6
  • 8

8 Answers8

113

Just change the id and re-insert.

> db.coll.insert({_id: 'hi', val: 1})
> var orig = db.coll.findOne({_id: 'hi'})
> orig._id = 'bye'
bye
> db.coll.insert(orig)
> db.coll.find()
{ "_id" : "hi", "val" : 1 }
{ "_id" : "bye", "val" : 1 }
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
  • 14
    If you want to clone the row, but without explicitely typing a new id, just delete the "_id" property before doing the insert command: delete orig._id – Emmanuel P. Feb 17 '17 at 11:41
37

You can give a new ObjectId to the copy Document. In mongo shell

var copy = db.collection.findOne();
for (var i = 0; i< 30; i++){ 
    copy._id = new ObjectId(); 
    db.collection.insert(copy);
}
689
  • 529
  • 5
  • 6
37

A little improvement to the @689 response

var copy = db.collection.findOne({},{_id:0});
for (var i = 0; i< 30; i++){ 
    db.collection.insert(copy);
}
pykiss
  • 949
  • 12
  • 15
24

You can use below code :

Run using single line :

db.collectionName.find({"_id" : ObjectId("5a4e47e0a21698d455000009")}).forEach(function(doc){var newDoc = doc; delete newDoc._id; db.collectionName.insert(newDoc); })

a structural format for understanding :

db.collectionName.find({"_id" : ObjectId("5a4e47e0a21698d455000009")}).forEach(function(doc){
    var newDoc = doc;
    delete newDoc._id;
    db.collectionName.insert(newDoc);
})
Irshad Khan
  • 5,670
  • 2
  • 44
  • 39
2

In mongo shell: It's OK

db.products.find().forEach( function(doc){db.products.insert(
{
    "price":doc.price,
    "name":doc.name,
    "typeName":doc.typeName,
    "image":doc.image
}
)} );
Tính Ngô Quang
  • 4,400
  • 1
  • 33
  • 33
2

Many of the previous answers are simple and correct, but they are not efficient if your goal is to copy all the documents in the collection with new _ids. Here is a three-line solution that was more than 10x faster for me:

First copy the collection efficiently:

db.collection.aggregate([{ $out: "collection_copy" }]);

Now pass documents from the copy back into the original, but remove the _id field so a new _id is generated:

db.collection_copy.aggregate([{$project: {_id: 0}}, { $merge: "collection" }]);

Finally, clean up the copy:

db.collection_copy.drop();
0

single line

(function(doc){delete doc._id; db.collection.insert(doc)})(db.collection.findOne({ _id: ObjectId("60c9a684c7d51907c35ad463")}))

structured

(function(doc) {
  delete doc._id;
  db.collection.insert(doc);
})(db.collection.findOne({ _id: ObjectId('60c9a684c7d51907c35ad463') }));

// (function(doc){...})(doc)
Alex
  • 29
  • 3
0

With a pipeline

db.collection.insertMany(
db.collection.aggregate([
    {
        $match: { _id: ObjectId("") }
    },
     
 { $unset: [ "_id"] }]).toArray());
Henry
  • 785
  • 9
  • 17