2010-04-09 40 views
23

Tengo una colección t1 con los siguientes campos en su esquemacampo de actualización con el valor de otro campo en el documento

_id, field1, field1 

QUIERO Establecer valor field2 's field1 como SQL:

update t1 set field1=field2; 

Cómo ¿Lo hago en MongoDB?

+1

pregunta muy similar: http://stackoverflow.com/questions/3974985/update-mongodb-field-using-value-of-another-field/ –

Respuesta

36

Buenas y malas noticias aquí.

Las malas noticias es que yo sepa no se puede hacer con una llamada única actualización() - mongo no soporta refiriéndose al objeto actual en la actualización.

Una buena noticia es que hay otras maneras de hacerlo, p. puede ejecutar un bucle foreach:

db.item.find(conditions...).forEach(function (doc) { 
    doc.field1 = doc.field2; 
    db.item.save(doc); 
}); 

Puede ejecutar forEach en el shell de administración ('mongo' comando), oa través de algunos de los métodos de su controlador específico (por ejemplo, en PHP que cabe esperar que funcione con mongodb.execute() tal como se describe aquí: http://www.php.net/manual/en/mongodb.execute.php)

+13

Debido a que una llamada a save() se está realizando de el bucle forEach, el cursor se arruinará y la función se llamará varias veces para cada documento. La solución es llamar a snapshot() antes de foreach: db.item.find (blah) .snapshot(). ForEach() –

+0

Gracias por eso. No estaba al tanto del requisito de instantánea() para que esto funcione según lo previsto. TBH Me sorprendió al principio que una función llamada "forEach" no garantiza lo que su nombre implica (porque es similar a lo que puede encontrar en las bibliotecas de colecciones en los lenguajes de programación), pero de nuevo, entiendo que puede haber muchas razones para hacer eso. –

+3

No hay forma atómica de hacer esto? Esta solución no parece muy sólida. – UpTheCreek

2

esto se puede hacer mediante:

db.nameOfCollection.find().forEach(
    function (elem) { 
     db.nameOfCollection.update(
      { 
       _id: elem._id 
      }, 
      { 
       $set: { 
        field2: elem.field1 
       } 
      } 
     ); 
    } 
); 
+2

Error al copiar y pegar de http://stackoverflow.com/a/14423151/2054072 –

8

partir de la versión 3.4, podemos usar el operador de canalización $addFields agregación a esta sin procesamiento del lado del cliente que es el más eficiente camino.

db.collection.aggregate(
    [ 
     { "$addFields": { "field2": "$field1" }}, 
     { "$out": "collection" } 
    ] 
) 

Antes de la versión 3.4 tenemos que recorrer el objeto Cursor y utilizar $set operador para añadir el nuevo campo con el valor "campo1" existente. Debe hacer esto usando la operación "bulk" para la máxima eficiencia.

MongoDB 3.2 rechaza Bulk() y su associated methods, por lo tanto, desde 3.2 hacia arriba, necesita utilizar el método bulkWrite.

var requests = []; 
db.collection.find({}, { 'field1': 1 }).snapshot().forEach(document => { 
    requests.push({ 
     'updateOne': { 
      'filter': { '_id': document._id }, 
      'update': { '$set': { 'field2': document.field1 } } 
     } 
    }); 
    if (requests.length === 1000) { 
     //Execute per 1000 operations and re-init 
     db.collection.bulkWrite(requests); 
     requests = []; 
    } 
}); 

if(requests.length > 0) { 
    db.collection.bulkWrite(requests); 
} 

Desde la versión 2.6 a 3.0, puede utilizar la API Bulk.

var bulk = db.collection.initializeUnorderedBulOp(); 
var count = 0; 

db.collection.find({}, { 'field1': 1 }).snapshot().forEach(function(document) { 
    bulk.find({ '_id': document._id }).updateOne({ 
     '$set': { 'field2': document.field1 } 
    }); 
    count++; 
    if(count%1000 === 0) { 
     // Excecute per 1000 operations and re-init 
     bulk.execute(); 
     bulk = db.collection.initializeUnorderedBulkOp(); 
    } 
}) 

// clean up queues 
if(count > 0) { 
    bulk.execute(); 
} 
+0

En mis pruebas, encontré que el método de agregación es MUCHO más rápido. Los datos de mi muestra tenían documentos de 150K que tardaban 5 segundos en remodelarse, mientras que los métodos .foreach tardaban ~ 1.5 minutos. ¿Qué se deben tener en cuenta cuando se aplica el enfoque de agregación? – Tung

Cuestiones relacionadas