2013-06-24 12 views
5

Muszę przeszukać zbiór dokumentów, ale także wszelkich poddokumentów i zmienić nazwę pola "en" na "en-GB" w każdym wystąpieniu, próbowałem tego kodu, ale ciągle otrzymuję wykonanie kodu JavaScript nie powiodło się: RangeError: przekroczono maksymalny rozmiar stosu wywołań. Problem polega na przeszukiwaniu subdokumentów za pomocą funkcji bez znajomości ścieżki.Wyszukiwanie rekursywne 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]); 
    } 
} 

}

Mam też coś podobnego, że zamiast dodaje go do kolejki przy użyciu tablicy napisane, ale potrzebny jest sposób zapisywania ścieżki podrzędne dokumenty, takie jak „document.subdocument”, a następnie uruchomiony ponownie poprzez funkcję, aby sprawdzić pole.

+0

Czy w obiekcie może znajdować się okrągłe odniesienie? X wskazuje na Y, Y wskazuje na Z, Z wskazuje na X? To spowodowałoby przepełnienie stosu. – Brandon

+0

Powinieneś użyć 'x [propt]' zamiast wartości 'propt', ponieważ jest to po prostu nazwa właściwości' x'. – WiredPrairie

Odpowiedz

3

Możesz spróbować czegoś jak poniżej.

pierwsze, wystarczy użyć przemianować na wszystkich dokumentów w kolekcji:

db.products.update({}, {$rename:{"en":"en-GB"}}, false, true); 

Nie ma powodu, aby to zrobić w funkcji przemapować. Ponadto używana składnia oznacza aktualizację wszystkich dokumentów (a nie konkretnego dokumentu) poprzez aktualizację en do en-GB.

Jeśli chcesz zaktualizować tylko jeden konkretny dokument, trzeba by określić dokument _id na przykład:

db.products.update({_id : x._id}, {$rename:{"en":"en-GB"}}, false, true); 

Następnie zmodyfikować funkcję przemapować pętli wszystkich właściwości każdego dokumentu, i chwyć wartość i sprawdź jej typ:

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

Może to być wywołane rekurencyjnie, jak pokazano. Jednak, to nie zmieni nazwy właściwości podobiektów. Jest to bardziej złożone i musisz przekazać pełny dokument dla każdego, zachować go rekurencyjnie, a następnie zaktualizować wszystkie właściwości dokumentu na raz (używając ścieżek właściwości, takich jak "subobject.locale" lub ponownie zapisując cały dokument). Tablice mogą być trudniejsze do zrobienia, ponieważ musisz usunąć obiekt z tablicy i ponownie wstawić go do tego samego indeksu z nowymi modyfikacjami (lub użyć specyfikatorów indeksu tablic). Jeśli zapiszesz cały dokument, możesz zmodyfikować je wszystkie na miejscu, co będzie prostsze.

Szczerze mówiąc, zrobiłbym to za pomocą twojego ulubionego języka programowania zamiast z powłoki w tym momencie.

+0

Czy jest możliwe zapisanie ścieżki dokumentacji poddokumentów, takiej jak "product.description", do napisu, który mógłbym następnie uruchomić przez funkcję. Potrzebuję sposobu skanowania wszystkich dokumentów i wszystkich dokumentów podrzędnych dla tego samego pola, a następnie trzeba zmienić jego nazwę. –

+0

W zależności od języka programowania, tak. Jeśli jest to tylko obiekt JavaScript, wystarczy ustawić wymagane właściwości. – WiredPrairie

Powiązane problemy