私のアプローチは、ドキュメントインスタンスを取得し、インスタンスフィールドから新しいインスタンスを作成することです。私はそれを行うためのより良い方法があると確信しています。
「コピー/クローン」の意味を明確にできますか?データベースに複製ドキュメントを作成しようとしていますか?または、重複するデータを持つ2つの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"
});
});
この場合、x
とy
は、プログラム内の同じドキュメントの2つの「コピー」になります。
または、ドキュメントの新しいコピーをデータベースに挿入したい場合(別の_id
を使用すると思いますが)、次のようになります。
Model.findById(yourid).exec(
function(err, doc) {
var d1 = doc;
d1._id = /* set a new _id here */;
d1.save(callback);
}
);
または、最初からこれを行っている場合、別名d1
というドキュメントを作成した場合は、_id
を設定せずにsave
を2回呼び出すだけです。
var d1 = new Model({ name: "John Doe", age: 54 });
d1.save(callback);
d1.save(callback);
これで、_id
が異なる2つのドキュメントと、データベース内の他のすべてのフィールドが同一になります。
これで少しわかりやすくなりますか?
上記のAmeliaの応答でドキュメントを複製する次のコード機能しません:
Model.findById(yourid).exec(
function(err, doc) {
var d1 = doc;
d1._id = /* set a new _id here */;
d1.save(callback);
}
);
リセットする必要もあります
d1.isNew = true;
のように:
Model.findById(yourid).exec(
function(err, doc) {
doc._id = mongoose.Types.ObjectId();
doc.isNew = true; //<--------------------IMPORTANT
doc.save(callback);
}
);
ドキュメントを複製する次のコード:
Model.findById(yourid).exec(
function(err, doc) {
var newdoc = new Model(doc);
newdoc ._id = mongoose.Types.ObjectId();
newdoc .save(callback);
}
);
単にクローンを作成するには、これを使用します:
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);
});
したがって、これらの回答の多くは単純なドキュメントではうまく機能しますが、複雑なドキュメントの深いクローンを作成しようとすると、エラーが発生する可能性があります。
たとえば、サブドキュメントの配列がある場合、コピーされたドキュメントで_idが重複してしまい、後で微妙なバグが発生する可能性があります。
マングースドキュメントのディープクローンを作成するには、次のようなことを試すことをお勧めします。
//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フィールドを使用して適切に複製されることを保証します。