2012-02-10 15 views
17

Vorrei aggiungere un nuovo campo a una raccolta, con il valore del nuovo campo impostato sul valore di un campo esistente.Aggiungere un nuovo campo a una raccolta con valore di un campo esistente

In particolare, mi piacerebbe andare da questo:

# db.foo.findOne() 
    { 
     "_id"  : ObjectId("4f25c828eb60261eab000000"), 
     "created" : ISODate("2012-01-29T16:28:56.232Z"), 
     "..."  : ... 
    } 

a questo:

# db.foo.findOne() 
    { 
     "_id"  : ObjectId("4f25c828eb60261eab000000"), 
     "created" : ISODate("2012-01-29T16:28:56.232Z"), 
     "event_ts" : ISODate("2012-01-29T16:28:56.232Z"), #same as created 
     "..."  : ... 
    } 

(Nuovi documenti di questa collezione non avranno tutti questa ridondanza peculiare, ma voglio per fare questo per i miei documenti esistenti)

+0

Quindi questa è una cosa da fare una volta sola? – ggreiner

+0

giusto, è sufficiente farlo una sola volta per preparare questi dati – Purrell

risposta

38
function addEventTsField(){ 
    db.foo.find().forEach(function(doc){ 
     db.foo.update({_id:doc._id}, {$set:{"event_ts":doc.created}}); 
    }); 
} 

Run dalla console:

addEventTsField(); 
+2

Tuttavia non un'operazione atomica. Si tratta di due operazioni separate con la possibilità che i dati cambino in mezzo. (anche se probabilmente è sicuro nel suo caso come sembra lo stia facendo una volta, offline) – UpTheCreek

2

No, non è possibile. Solo due passaggi che probabilmente conosci:

  1. Caricare il documento, leggere il campo. (È possibile caricare solo specific fields: _id e created nel tuo caso se le prestazioni sono un problema)
  2. atomica aggiornamento e documenti (impostare event_ts utilizzando caricato created campo)
+0

Neanche con qualcosa con db.foo.find(). ForEach()? – Purrell

+1

@Purrell: 'forEach' in realtà carica tutti i documenti trovati, e diventa un aggiornamento di due passi ... –

-1

poiché il codice sa già come gestire event_ts perché è necessario copiare i dati? è possibile rinominare il campo, invece:

{ $rename : { old_field_name : new_field_name } } 

Vedi http://www.mongodb.org/display/DOCS/Updating

+4

Stai facendo una supposizione, che "creato" non è anche necessario nei documenti. – Purrell

-1

Se si tratta di una cosa di una volta di fare, la sua non un grosso problema. Esegui una query come "db.foo.find();" nel tuo mongo shel e incolla l'intero output in un editor come Textpad o Sublime text, fai un blocco di colonne (nel testo sublime è Ctrl + scroll scroll click & Drag),, incollalo che si estenderà in un altro campo, rinomina il nuovo colonna incollata come desideri, una volta eseguita, esegui un'espressione regolare per modificare l'intero gruppo come "^" con "db.foo.insert ({" e al "$" come "});"

È come i seguenti passaggi.

  1. incollato l'output come { 'field1': valore, 'field2': valore2, 'field3': valore4};
    1. copia l'ultimo set ed estendi utilizzando il blocco di colonna dell'editor {'field1': value, 'field2': value2, 'field3': value4};
    2. Ora inserisci le parole appropriate per farlo apparire come un comando per mongo db.foo.insert ({'campo1': valore, 'campo2': valore2, 'campo3': valore4});
    3. Ora copialo tutti e incollalo nella tua shell mongo, che farà tutto per te come desideri. Provalo una volta e rifai tutto subito dopo aver ripulito la raccolta altrimenti inserirà i duplicati. Rimuovete anche i campi "_id" nell'output poiché entrerà in conflitto quando provate ad inserire di nuovo !!

Ora, ogni singola riga nel vostro editor mostra un comando Mongo valido che può essere incollato alla vostra shell per inserire un nuovo documento alla tua collezione. quindi testalo una volta e funziona bene, ripulisci l'intera raccolta come "db.foo.remove ({});" e incolla l'intero comando dall'editor che lo farà in un giffy.

Potrebbe essere difficile quando provi per la prima volta, ma se lo fai bene sarà una cosa utile per farti lavorare quando lo vuoi .... !!

+0

Questa risposta non ha senso, poiché è talmente soggetta a errori, non può essere automatizzata, non può essere testata, non può essere sottoposta a script ... Perché mai dovresti voler fare questa operazione in un editor, quando può essere fatto così facilmente con una funzione semplice e forEach()? –

+0

Anche -1 perché richiede 'db.foo.remove ({})' nel mezzo dell'operazione, il che rovinerebbe qualsiasi cosa aspettandosi che i dati esistenti siano ancora lì. – David

+0

La domanda è stata pubblicata con l'intento che è un lavoro di una volta. Inoltre, farlo in editor rende molto più facile ciò che deve essere modificato, cosa deve essere commentato o cosa deve essere rimosso. Ovviamente la soluzione che utilizza foreach è migliore, anche questo non è poi così male visto che è molto utile quando siamo nel mezzo di test in cui dobbiamo inserire dati abbastanza frequentemente, rimuoverli, aggiungerli di nuovo con poche modifiche qui n lì ecc. Può anche essere automatizzato quando si esegue lo stesso file di script in riga di comando. – Param

Problemi correlati