26

我的方法是获取文档实例,并从实例字段创建一个新实例。我确信有更好的方法来做到这一点。

4

9 回答 9

88

您需要重置d1.isNew = true;为:

Model.findById(yourid).exec(
    function(err, doc) {
        doc._id = mongoose.Types.ObjectId();
        doc.isNew = true; //<--------------------IMPORTANT
        doc.save(callback);
    }
);
于 2014-09-15T10:09:01.677 回答
13

您能否澄清“复制/克隆”的含义?您是否要尝试在数据库中创建重复文档?或者你只是想var在你的程序中有两个 s 有重复的数据?

如果你只是这样做:

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"
            }); 
    });

在这种情况下,xy将是您程序中同一文档的两个“副本”。

或者,如果您想将文档的新副本插入数据库(尽管_id我假设使用不同的副本),则如下所示:

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

或者如果你从一开始就这样做,也就是你创建了一些文档d1,你可以调用save两次而不设置_id

var d1 = new Model({ name: "John Doe", age: 54 });
d1.save(callback);
d1.save(callback);

现在将有两个文档_id在您的数据库中具有不同的 ' 和所有其他字段相同。

这是否澄清了一些事情?

于 2013-09-19T14:41:55.830 回答
3

因此,这些答案中的很多都适用于简单的文档,但是当您尝试对复杂文档进行深度克隆时,可能会出现错误情况。

例如,如果您有子文档数组,则最终可能会在复制的文档中出现重复的 _id,这可能会导致稍后出现细微的错误。

要对 mongoose 文档进行深度克隆,我建议尝试以下操作:

//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();

这将是一种非常安全的方法,并将确保对象的每个部分都在保存时使用新生成的 _id 字段正确克隆。

于 2020-02-20T19:58:41.380 回答
3

我的两分钱:

const doc = await DocModel.findById(id);
let obj = doc.toObject();
delete obj._id;
const docClone = new DocModel(obj);
await docClone.save();
于 2021-05-14T00:01:12.823 回答
2

以下代码克隆文档:

Model.findById(yourid).exec(
        function(err, doc) {
            var newdoc = new Model(doc);
            newdoc._id = mongoose.Types.ObjectId();
            newdoc.save(callback);
        }
    );
于 2015-04-02T05:48:55.203 回答
1

对于简单的克隆使用这个:

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);
    });
于 2017-06-26T09:09:14.003 回答
0
const cloneDoc = (doc, model)=>{
  const copyDoc = new Model({
    ...doc.toObject(),
    _id: undefined,
  });
  copyDoc.isNew = true;
  return copyDoc;
}
于 2021-06-18T23:42:31.060 回答
0

您基本上可以使用 .clone() 来获取副本。

const cars = Cars.find();
const carsCopy = cars.clone();

await cars;
await carsCopy;

https://mongoosejs.com/docs/api.html#schema_Schema-clone

于 2022-01-25T08:48:12.247 回答
0

要将文档复制到同一集合或不同集合中,首先获取(查询)数据并制作数据副本。然后从新列表中删除 _id ,因为您不能从当前数据中删除。这将允许您使用从 mongodb 分配的新 _id 插入新记录

将 searchBy 更改为您尝试查找文档的内容。将 collectionA 和 collectionB 更改为要创建复制到的集合的名称。目前我们正在collectionA中搜索并复制collectionB中的数据

collectionA.find(searchBy).exec(function (err, doc) {
      // create a new copy
      let newDoc = { ...doc[0] }._doc;

      // delete property from new copy (remove _id).
      delete newDoc._id;

      // insert copy into db
      var newdoc = new collectionB(newDoc);
      newdoc.save();
    });
于 2021-09-24T22:06:49.543 回答