2013-06-24 4 views
5

Мне нужно выполнить поиск по коллекции документов, а также любых вложенных документов и переименовать поле «en» в «en-GB» в каждом случае, я пробовал этот код, но продолжал выполнять выполнение JavaScript: RangeError: Максимальный размер стека вызовов превышен. Проблема заключается в поиске вложенных документов с использованием функции, не зная пути.Mongodb рекурсивный поиск

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

Может ли быть круговая ссылка в объекте? X указывает на Y, Y указывает на Z, Z указывает на X? Это приведет к переполнению стека. – Brandon

+0

Вы должны использовать 'x [propt]', а не значение 'propt', так как это просто имя свойства' x'. – WiredPrairie

ответ

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); 

Затем измените функцию ReMap перебрать все свойства каждого документа, и возьмите это значение и проверьте его тип:

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" или сохранить весь документ). Массивы могут быть сложнее сделать, поскольку вам нужно удалить объект в массиве и повторно вставить его в тот же индекс с новыми изменениями (или использовать спецификаторы индекса массива). Если вы сохраните весь документ, вы можете изменить их все на месте, что было бы проще.

Честно говоря, я бы сделал это, используя ваш любимый язык программирования, а не из оболочки на этом этапе.

+0

Возможно ли сохранить путь поддокументов, такой как «product.description», к строке, которую я мог бы запустить через эту функцию. Мне нужен способ сканирования всех документов и всех поддокументов для одного и того же поля, а затем необходимо переименовать его. –

+0

В зависимости от языка программирования, да. Если это всего лишь объект JavaScript, вы просто установите необходимые свойства. – WiredPrairie