Easiest way to copy/clone a mongoose document instance?

前端 未结 5 1392
时光说笑
时光说笑 2020-12-09 09:31

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.

相关标签:
5条回答
  • 2020-12-09 09:57

    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.

    0 讨论(0)
  • 2020-12-09 09:59

    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);
            }
        );
    
    0 讨论(0)
  • 2020-12-09 10:03

    The following code to clone documents in Amelia's response above does not work:

    Model.findById(yourid).exec(
        function(err, doc) {
            var d1 = doc;
            d1._id = /* set a new _id here */;
            d1.save(callback);
        }
    );
    

    You also 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);
        }
    );
    
    0 讨论(0)
  • 2020-12-09 10:03

    For simply clone use this :

    Context.findOne({
        _id: context._id
    })
        .then(function(c) {
            c._id = undefined;
            c.name = context.name;
            c.address = context.address;
            c.created = Date.now();
            return Context.create(c.toObject());
        }).then(function(c) {
            return res.json({
                success: true,
                context: context
            });
        }).catch(function(err) {
            next(err, req, res);
        });
    
    0 讨论(0)
  • 2020-12-09 10:17

    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 vars 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.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?

    0 讨论(0)
提交回复
热议问题