我需要搜索一组文档以及任何子文档,并在每次出现时将标题为“en”的字段重命名为“en-GB”,我已经尝试过此代码但仍然无法执行JavaScript:RangeError:Maximum调用堆栈大小超出错误。问题是在不知道路径的情况下使用函数搜索子文档。
remap = function (x) {
if (x.en){
db.products.update({_id:x._id}, {$rename:{"en":"en-GB"}}, false, true); }
for (var propt in x) {
if (Object.prototype.toString.call( x[propt] ) === '[object Array]' ||
Object.prototype.toString.call( x[propt] ) === '[object Object]'){
remap(x[propt]);
}
}
}
我也写过类似的内容,而是使用数组将其添加到队列中,但是需要一种方法来保存子文档路径,例如“document.subdocument”,然后再次通过该函数运行它来检查字段。
答案 0 :(得分:3)
您可以尝试下面的内容。
首先,只需对集合中的所有文档使用重命名:
db.products.update({}, {$rename:{"en":"en-GB"}}, false, true);
在重映射功能中没有理由这样做。此外,您使用的语法意味着通过将en
更新为en-GB
来更新所有文档(而非特定文档)。
如果您只想更新单个特定文档,则需要按_id
指定文档,例如:
db.products.update({_id : x._id}, {$rename:{"en":"en-GB"}}, false, true);
然后,修改您的重映射函数以遍历每个文档的所有属性,并获取值并检查其类型:
var remap = function (x) {
for (var propt in x) {
var val = x[propt];
var type = Object.prototype.toString.call( val );
if (type === '[object Array]' || type === '[object Object]') {
remap(val);
}
}
};
可以递归调用,如图所示。 但是,这不会重命名子对象的属性。这更复杂,您需要为每个文档传递完整文档,递归维护它,然后立即更新文档的所有属性(使用属性路径,如"subobject.locale"
或重新保存整个文档)。数组可能更难以实现,因为您需要删除数组中的对象,并使用新修改将其重新插入相同的索引(或使用数组索引说明符)。如果您保存整个文档,则可以将其全部修改,这样会更简单。
老实说,我会用你最喜欢的编程语言而不是shell来做这件事。