Easiest way to copy/clone a mongoose document instance?
Solution 1
Can you clarify what you mean by "copy/clone"? Are you going trying to create a duplicate document in the database? Or are you just trying to have two var
s in your program that have duplicate data?
If you just do:
Model.findById(yourid).exec(
function(err, doc) {
var x = doc;
Model.findById(yourid).exec(
function(err, doc2) {
var y = doc2;
// right now, x.name and y.name are the same
x.name = "name_x";
y.name = "name_y";
console.log(x.name); // prints "name_x"
console.log(y.name); // prints "name_y"
});
});
In this case, x
and y
will be two "copies" of the same document within your program.
Alternatively, if you wanted to insert a new copy of the doc into the database (though with a different _id
I assume), that would look like this:
Model.findById(yourid).exec(
function(err, doc) {
var d1 = doc;
d1._id = /* set a new _id here */;
d1.isNew = true;
d1.save(callback);
}
);
Or if you're doing this from the outset, aka you created some document d1
, you can just call save
twice without setting the _id
:
var d1 = new Model({ name: "John Doe", age: 54 });
d1.save(callback);
d1.save(callback);
There will now be two documents with differing _id
's and all other fields identical in your database.
Does this clarify things a bit?
Solution 2
You need to reset d1.isNew = true;
as in:
Model.findById(yourid).exec(
function(err, doc) {
doc._id = mongoose.Types.ObjectId();
doc.isNew = true; //<--------------------IMPORTANT
doc.save(callback);
}
);
Solution 3
My two cents:
const doc = await DocModel.findById(id);
let obj = doc.toObject();
delete obj._id;
const docClone = new DocModel(obj);
await docClone.save();
Solution 4
So, a lot of these answers will work well for simple docs, but there could be an error case when you're trying to make a deep clone of complex documents.
If you have arrays of subdocs, for example, you can end up with duplicate _ids in your copied document, which can cause subtle bugs later.
To do a deep clone of a mongoose doc, I suggest trying something like:
//recursively remove _id fields
function cleanId(obj) {
if (Array.isArray(obj))
obj.forEach(cleanId);
else {
delete obj['_id'];
for (let key in obj)
if (typeof obj[key] == 'object')
cleanId(obj[key]);
}
}
let some_doc = await SomeModel.findOne({_id: some_id});
let new_doc_object = cleanId(some_doc.toObject());
let new_doc = new SomeModel(new_doc_object);
await new_doc.save();
This is going to be a pretty safe approach, and will ensure that every part of your object is cloned properly with newly generated _id fields on save.
Solution 5
The following code to clone documents:
Model.findById(yourid).exec(
function(err, doc) {
var newdoc = new Model(doc);
newdoc._id = mongoose.Types.ObjectId();
newdoc.save(callback);
}
);
Related videos on Youtube
fusio
Updated on January 25, 2022Comments
-
fusio over 2 years
My approach would be to get the document instance, and create a new one from the instance fields. I am sure there is a better way to do it.
-
fusio almost 11 yearsYes, indeed, I ended up getting the
doc
, removing_id
and saving :) -
JoeTidee over 7 yearsHow did you remove the _id?
-
Will Brickner over 7 years@JoeTidee You can use
delete doc._id
will remove the_id
property from thedoc
object! -
losnir almost 7 yearsThis does not answer the question unfortunately. To truly clone a document, you would do:
new Model(doc.toObject())
. -
Iron_Man over 6 yearsWhat are the approaches for copying the entire collection and create it with new name Through Mongoose? As I know how to clone/Copy the collection through cmd, But this things not work on mongoose. Any help is appreciated
-
Ninja Coding almost 6 yearssorry but this answer is bad, you just can do: var doc1= doc.toJSON(); var doc2= doc.toJSON(); and you have 2 objects with same data, no query.
-
Amr Saber about 5 yearsyou could have commented on her answer or edited the answer !
-
David J over 3 yearsGreat answer but, this does not work as expected. You cannot delete an _id on a Mongoose object. Second, the id is created on the local object, so saving twice does not create two identical objects. It just saves the same document twice. Even if you create a new id. This might be a version thing as this answer is from 2013. Maybe it used to work.
-
David J over 3 yearsThis also does not work. Perhaps it's a version thing since this is 2014. Maybe it used to work.
-
David J over 3 yearsThis might be more simply stated as you just have to copy object properties. I've not found any of the approaches to work.
-
sean almost 3 yearsIsn't
exec
redundant here -
taseenb about 2 yearsThis example will clone the schema, not the document