I need to search through a collection of documents but also any subdocuments and rename a field titled "en" to "en-GB" in every occurrence, I have tried this code but keep getting a JavaScript execution failed: RangeError: Maximum call stack size exceeded error. The problem is searching through the subdocuments using the function without knowing there path.
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]);
}
}
}
I have also written something similar that instead adds it to a queue using an array, but need a way of saving the sub-documents path such as "document.subdocument" and then running it through the function again to check for the field.
Definition. $graphLookup. Changed in version 5.1. Performs a recursive search on a collection, with options for restricting the search by recursion depth and query filter.
In MongoDB, we can perform text search using text index and $text operator. Text index: MongoDB proved text indexes that are used to find the specified text from the string content. Text indexes should be either a string or an array of string elements.
It is slow because it is not using an index. For each document in the logs collection, it is doing a full collection scan on the graphs collection.
In MongoDB, one-to-one, one-to-many, and many-to-many relations can be implemented in two ways: Using embedded documents. Using the reference of documents of another collection.
You might try something like below.
First, just use rename on all documents in the collection:
db.products.update({}, {$rename:{"en":"en-GB"}}, false, true);
There's no reason to do that in the remap function. Further, the syntax you used means update all documents (not a specific document) by updating en
to en-GB
.
If you wanted to update just a single specific document, you'd need to specify the document by _id
for example:
db.products.update({_id : x._id}, {$rename:{"en":"en-GB"}}, false, true);
Then, modify your remap function to loop through all properties of each document, and grab the value and check its type:
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);
}
}
};
It could be recursively called as shown. However, this won't rename the properties of sub-objects. That's more complex and you'll need to pass in the full document for each, maintain it recursively, and then update all properties of the document at once (using property paths, like "subobject.locale"
or resaving the entire document). Arrays may be more difficult to do in place, as you'll need to remove the object in the array, and reinsert it at the same index with the new modifications (or use array index specifiers). If you save the entire document, you could modify them all in place, which would be simpler.
Honestly, I'd do this using your favorite programming language rather than from the shell at this point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With