2011-09-13 14 views
14

Tengo un campo en mongodb que es una cadena. {"field": "some text"}, quiero convertirlos a todos en matrices. {"field": ["some text"]}mongodb tipo cambiar a matriz

Sé que puedo recorrer todos los documentos, obtener el campo y luego actualizar, pero me pregunto si hay una manera más clara.

Gracias.

Respuesta

3

Puede hacerlo en una función Reduce de map/reduce para mantener todo el procesamiento en mongodb. Esencialmente usaría map/reduce para poner los resultados en una nueva colección y luego podría copiarlos a la colección anterior (o eliminar la anterior y cambiarle el nombre a la nueva). Esto tiene la ventaja de mantener todo dentro de mongo.

Actualización: Otra opción podría ser utilizar db.eval para esto. db.eval se ejecuta en el servidor para que las actualizaciones se realicen en el servidor sin tráfico/latencia.

Creo que la única otra opción es la que usted describió: hágalo en el cliente consultando y actualizando cada una.

+0

¿Cree que el MapReduce en mongo será más rápido? – Harry

+0

Principalmente depende de cuántos documentos y cuántos datos se están moviendo entre el servidor y el cliente. Si hay una gran cantidad de datos en movimiento entre el servidor/cliente, entonces desea mantener el procesamiento dentro de MongoDB con mapReduce o pruebe con db.eval (como acabo de agregar en una edición anterior). –

+0

gracias por db.eval, siempre feliz de aprender algo nuevo. – Harry

0

pero me pregunto si hay una forma más limpia ..

La respuesta corta es no.

MongoDB no tiene ninguna operación o comando para realizar un "tipo de cambio".

La forma más rápida de hacer esto es utilizar uno de los controladores y realizar el cambio. Puede usar el shell y escribir un ciclo for, pero en términos de velocidad bruta, los otros controladores pueden ser más rápidos.

Dicho esto, la parte más lenta del proceso será cargar todos los datos del disco en la memoria para ser cambiados y luego volver a tirarlos a la memoria. Esto sería cierto incluso con un comando mágico de "tipo de cambio".

3

Tal vez puedas probar

Esto es para cambiar el tipo de un campo de cadena en serie en MongoDB

db.jobs.find({ "jobLocationCity" : { $type : 2 } }).forEach(function (x) { 
    x.jobLocationCity = {"Location":x.jobLocationCity}; 
    db.jobs.save(x); 
}); 

ver el enlace de respuesta $ de tipo possible values

+0

Esta respuesta me llevó a una solución que considero muy sucinta. El problema que tuve con el ejemplo proporcionado aquí es que debido a que se está realizando una llamada a save() dentro del bucle forEach, el cursor se estaba desordenando y la función se llamaría varias veces para el mismo documento. La solución es llamar a snapshot() antes de foreach: db.jobs.find (blah) .snapshot(). ForEach() –

10

Nitin de Garg por encima de casi funciona, excepto que su ejemplo se convierte de una cadena a un hash, NO una cadena a una matriz.

Teniendo en cuenta los comentarios de Joel Harris, la solución adecuada sería el resultado:

db.jobs.find({ "jobLocationCity" : { $type : 2 } }).snapshot().forEach(function (x) { 
    x.jobLocationCity = [ jobLocationCity ]; 
    db.jobs.save(x); 
}); 

O si se utiliza db.eval:

function f() { 
    db.jobs.find({ "jobLocationCity" : { $type : 2 } }).snapshot().forEach(function (x) { 
     x.jobLocationCity = [ jobLocationCity ]; 
     db.jobs.save(x); 
    }); 
} 
db.eval(f); 
+2

pequeña corrección: x.jobLocationCity = [x.jobLocationCity]; – Vitamon

+0

¿Por qué 'save' y no' update'? – nilskp

5

En realidad, el hallazgo ({ "jobLocationCity": { $ type: 2}}) no funcionará correctamente, porque si ejecuta la secuencia de comandos de actualización la próxima vez, tratará los elementos ['mystring'] de nuevo como tipo de cadena.

Debe utilizar algo como esto para evitar que:

db.message_info.find({ "jobLocationCity" : { $type : 2 } } ).snapshot().forEach(
    function (x) { 
    if (!Array.isArray(x.jobLocationCity)){ 
     x.jobLocationCity = [ x.jobLocationCity ]; 
     db.jobs.save(x); 
    } 
    } 
) 

ver http://docs.mongodb.org/manual/reference/operators/