我有一个带有嵌套属性的Collection,它是ObjectId References的数组。这些是指另一个Collection中的文档。
我想用文档本身替换这些引用,即将这些文档嵌入到引用现在的位置。我已尝试使用和不使用.snapshot()选项。这可能是因为我在该文档的循环中更新文档,并且.snapshot()在该级别不可用。
我的mongo-fu很低,而且我遇到了一个调用堆栈错误。我怎样才能做到这一点?感谢
示例代码:
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}} )
});
});
给出了这个错误:
{
"message" : "Maximum call stack size exceeded",
"stack" : "RangeError: Maximum call stack size exceeded" +
....}
答案 0 :(得分:0)
我认为这是因为两个原因之一。要么通过在for循环中执行两个查询来耗尽内存,要么在查找操作完成之前执行更新操作。
无论哪种方式,在for循环中执行太多查询都不是一个好主意,因为它可能导致此类错误。
我无法确定这是否会解决您的问题,因为我不知道您的馆藏中有多少文件,但如果您首先从CollWithReferences
馆藏中获取所有文件,那么它可能会有效你需要CollOfThingsToEmbed
集合。然后从_id
集合构建一个CollOfThingsToEmbed
的映射到与之对应的实际文档。然后,您可以遍历从CollWithReferences
集合中获取的每个文档,并通过访问每个groupsOfStuff
数组并将ObjectId设置为您在地图中具有的值来改变ArrayOfReferenceObjectIds
数组已经建成,这将是整个文件。然后,只需将GroupsOfSuff
设置为其变异值即可更新该文档。
以下JavaScript代码将执行此操作(可以更好地组织它以在全局范围内没有逻辑等):
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}
});
}
如果可以只进行一次批量更新会更好,但由于每个文档需要以不同方式更新,这是不可能的。