:
db.CollWithReferences.find({}).snapshot().forEach(function(document) {
var doc_id = document._id;
document.GroupsOfStuff.forEach(function(Group) {
var docsToEmbed= db.CollOfThingsToEmbed.find({ _id: { $in: Group.ArrayOfReferenceObjectIds }});
db.CollWithReferences.update({"_id": ObjectId(doc_id) },
{$set: {"Group.ArrayOfReferenceObjectIds ":docsToEmbed}})
});
});
は、このエラーが発生します。 forループで2つのクエリを実行してメモリが不足しているか、検索操作が完了する前に更新操作が実行されています。
いずれにしても、このタイプのエラーにつながる可能性があるので、forループで多すぎるクエリを実行することはお勧めできません。
コレクションに含まれるドキュメントの数がわからないため、これで問題が解決するかどうかはわかりませんが、最初にCollWithReferences
コレクションからすべてのドキュメントを取得してから、 CollOfThingsToEmbed
コレクション。その後、CollOfThingsToEmbed
コレクションの_id
のマップを、それに対応する実際の文書に作成します。次に、CollWithReferences
コレクションから取得した各ドキュメントをループし、groupsOfStuff
配列にそれぞれArrayOfReferenceObjectIds
配列にアクセスして、ObjectIdをドキュメント全体の値に設定して変異させることができます。その後、GroupsOfSuff
をその変更された値に設定して、その文書を更新してください。
次のJavaScriptコードは、これを行います(グローバルスコープなどにはロジックがないために、より良い組織化することができる):それはちょうど1回のバルク更新を行うことが可能であった場合
var references = db.CollWithReferences.find({});
function getReferenceIds(references) {
var referenceIds = [];
for (var i = 0; i < references.length; i++) {
var group = references[i].GroupsOfStuff;
for (let j = 0; j < group.ArrayOfReferenceObjectIds; j++) {
referenceIds.push(group.ArrayOfReferenceObjectIds[j]);
}
}
return referenceIds;
}
function buildIdMap(docs) {
var map = {};
for (var i = 0; i < docs.length; i++) {
map[docs[i]._id.toString()] = docs[i];
}
return map;
}
var referenceIds = getReferenceIds(references);
var docsToEmbed = db.CollOfThingsToEmbed.find({_id: {$in: referenceIds}});
var idMap = buildIdMap(docsToEmbed);
for (var i = 0; i < references.length; i++) {
var groups = references[i].GroupsOfStuff;
for (var j = 0; j < groups.length; j++) {
refs = groups[j].ArrayOfReferenceObjectIds;
refs.forEach(function(ref) {
ref = idMap[ref.toString()];
});
}
db.CollWithReferences.update({
_id: ObjectId(ref._id)
}, {
$set: {GroupsOfStuff: groups}
});
}
は、それが良いだろうしただし、各文書を別々に更新する必要があるため、これは不可能です。