2012-02-10 23 views
17

Me gustaría agregar un nuevo campo a una colección, con el valor del nuevo campo establecido en el valor de un campo existente.Agregar un nuevo campo a una colección con valor de un campo existente

En concreto, me gustaría ir de esto:

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

a esto:

# 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 
     "..."  : ... 
    } 

(Nuevos documentos de esta colección será no todos tienen esta peculiar redundancia, pero quiero para hacer esto para mis documentos existentes)

+0

¿Entonces esto es algo que debe hacer una sola vez? – ggreiner

+0

a la derecha, solo necesita hacerlo una vez para preparar esta información – Purrell

Respuesta

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

Ejecutar en la consola:

addEventTsField(); 
+2

Sin embargo, no es una operación atómica. Estas son dos operaciones separadas con la posibilidad de que los datos cambien entre medio. (aunque probablemente esté a salvo en su caso, ya que parece que lo está haciendo una vez, fuera de línea) – UpTheCreek

2

No, no es posible. Solo hay dos pasos que probablemente sepa:

  1. Cargue el documento, lea el campo. (Se puede cargar sólo specific fields: _id y created en su caso, si el rendimiento es un problema)
  2. actualización atómica del documento (establecido event_ts utilizando cargada campo created)
+0

Ni siquiera con algo con db.foo.find(). ForEach()? – Purrell

+1

@Purrell: 'forEach' en realidad carga todos los documentos encontrados, y se convierte en dos pasos de actualización ... –

-1

dado que su código ya sabe cómo manejar event_ts ¿por qué necesita copiar los datos? puede cambiar el nombre del campo en su lugar:

{ $rename : { old_field_name : new_field_name } } 

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

+4

Está asumiendo que 'creado' no es necesario en los documentos. – Purrell

-1

Si es una cosa de una vez a hacer, su no es gran cosa. Ejecute una consulta como "db.foo.find();" en su mongo shel y pegue todo el resultado a un editor como Textpad o Sublime text, haga un bloque de columna (En texto sublime Ctrl + rueda de desplazamiento haga clic & Arrastrar), péguelo, que se extenderá a otro campo, cambie el nombre del nuevo pegar la columna como quieras, una vez hecho, haz una expresión regular para editar todo el grupo como "^" con "db.foo.insert ({" y en "$" como "});"

Es como los siguientes pasos.

  1. que ha pegado la salida como { 'campo1': valor, 'campo2': valor2, 'field3': valor4};
    1. copie el último conjunto y extiéndalo utilizando el editor columna bloque {'campo1': valor, 'campo2': valor2, 'campo3': valor4};
    2. Ahora inserte las palabras adecuadas para que parezca un comando para mongo db.foo.insert ({'campo1': valor, 'campo2': valor2, 'campo3': valor4});
    3. Ahora cópielas todas y péguelas en su mongo shell, que lo hará por usted como usted lo desee. Pruébelo una vez y vuelva a hacer todo justo después de limpiar la colección, de lo contrario insertará duplicados. Elimine también los campos "_id" en la salida, ya que entrarán en conflicto cuando intente insertar nuevamente.

Ahora, cada línea en el editor muestra un comando mongo válida que se puede pegar a su shell para insertar un nuevo documento a su colección. así que pruébelo una vez y funciona bien, limpie toda su colección como "db.foo.remove ({});" y pegue todo el comando del editor, que lo hará en un giffy.

Puede ser difícil cuando intentas por primera vez, pero si lo haces bien será una herramienta útil para que trabajes cuando quieras ... !!

+0

Esta respuesta ni siquiera tiene sentido, ya que es tan propensa a errores, no se puede automatizar, no se puede probar, no se puede escribir ... ¿Por qué querría hacer esta operación en un editor, cuando se puede hacer tan fácilmente con una función simple y paraEach()? –

+0

También -1 porque requiere 'db.foo.remove ({})' en el medio de la operación, lo que arruinaría cualquier cosa esperando que los datos existentes todavía estén allí. – David

+0

La pregunta fue publicada con la intención de que sea un trabajo de una sola vez. Además, hacerlo en el editor facilita mucho lo que debe editarse, qué comentar o qué eliminar. Por supuesto, la solución que usa foreach es mejor, esto tampoco es tan malo, ya que es muy útil cuando estamos en medio de pruebas en las que tenemos que insertar datos con bastante frecuencia, eliminarlos, volver a agregarlos con pocos cambios aquí n etc., también se puede automatizar cuando solo ejecuta el mismo archivo de script en la línea de comandos. – Param

Cuestiones relacionadas