2013-06-24 16 views
5

Ho bisogno di cercare attraverso una raccolta di documenti ma anche qualsiasi documento secondario e rinominare un campo intitolato "en" a "en-GB" in ogni occorrenza, ho provato questo codice ma continuo a ottenere un'esecuzione JavaScript fallita: RangeError: errore di dimensione massima dello stack delle chiamate superato. Il problema è cercare tra i documenti secondari utilizzando la funzione senza conoscere il percorso.Ricerca ricorsiva in 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]); 
    } 
} 

}

Ho anche scritto qualcosa di simile che invece lo aggiunge a una coda utilizzando una matrice, ma hanno bisogno di un modo di salvare il percorso sotto-documenti quali "document.subdocument" e quindi eseguire di nuovo attraverso la funzione per verificare il campo.

+0

Potrebbe esserci un riferimento circolare nell'oggetto? X punta a Y, Y punta a Z, Z punta a X? Ciò causerebbe un overflow dello stack. – Brandon

+0

Dovresti usare 'x [propt]' piuttosto che il valore di 'propt', poiché questo è solo il nome della proprietà di' x'. – WiredPrairie

risposta

3

Si potrebbe provare qualcosa di simile qui sotto.

In primo luogo, basta usare rinominare su tutti i documenti della collezione:

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

Non c'è motivo di farlo nella funzione Remap. Inoltre, la sintassi che hai usato significa aggiornare tutti i documenti (non un documento specifico) aggiornando en a en-GB.

Se si voleva aggiornare un solo documento specifico, avresti bisogno di specificare il documento _id ad esempio:

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

Quindi, modificare la funzione di rimappatura a ciclo attraverso tutte le proprietà di ogni documento, e prendi il valore e controlla il suo tipo:

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

Potrebbe essere chiamato in modo ricorsivo come mostrato. Tuttavia,, questo non rinomina le proprietà degli oggetti secondari. È più complesso e dovrai passare il documento completo per ciascuno, mantenerlo in modo ricorsivo e quindi aggiornare tutte le proprietà del documento contemporaneamente (usando percorsi di proprietà, come "subobject.locale" o salvando nuovamente l'intero documento). Gli array possono essere più difficili da eseguire, poiché è necessario rimuovere l'oggetto nell'array e reinserirlo nello stesso indice con le nuove modifiche (o utilizzare gli specificatori di indice dell'array). Se si salva l'intero documento, è possibile modificarli tutti in posizione, il che sarebbe più semplice.

Onestamente, lo farei usando il tuo linguaggio di programmazione preferito piuttosto che dalla shell a questo punto.

+0

È possibile salvare il percorso dei documenti secondari come "product.description" in una stringa che è quindi possibile eseguire attraverso la funzione. Ho bisogno di un modo di scansionare tutti i documenti e tutti i documenti secondari per lo stesso campo, e quindi ho bisogno di rinominarlo. –

+0

A seconda del linguaggio di programmazione, sì. Se si tratta solo di un oggetto JavaScript, devi semplicemente impostare le proprietà necessarie. – WiredPrairie