I have a collection t1
with the following fields in its schema
_id, field1, field1
I want set field2
's value field1
like sql:
update t1 set field1=field2;
How do I do it in MongoDB?
Starting from MongoDB 4.2 you can perform Updates with an Aggregation Pipeline. An aggregation pipeline enables more expressive updates including calculated fields and references to other field values in the same document.
You can use aggregate function to update MongoDB field using the value of another field. Here, we will create two collections: name.
Good and bad news here.
Bad news is that AFAIK you can't do it with a single update() call - mongo doesn't support referring to current object in update.
Good news is that there are other ways to do it, e.g. you can run a forEach loop:
db.item.find(conditions...).snapshot().forEach( function (doc) { doc.field1 = doc.field2; db.item.save(doc); });
You can run forEach in the admin shell ('mongo' command), or through some of the methods of your specific driver (e.g. in PHP I'd expect it to work with mongodb.execute() as described in here: http://www.php.net/manual/en/mongodb.execute.php)
Starting from version 3.4, we can use the $addFields
aggregation pipeline operator to this without client side processing which is the most efficient way.
db.collection.aggregate( [ { "$addFields": { "field2": "$field1" }}, { "$out": "collection" } ] )
Prior to version 3.4 we need to iterate the Cursor
object and use $set
operator to add the new field with the existing "field1" value. You need to do this using "bulk" operation for maximum efficiency.
MongoDB 3.2 deprecates Bulk()
and its associated methods, thus from 3.2 upwards you need to use the bulkWrite
method.
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); }
From version 2.6 to 3.0 you can use the Bulk
API.
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(); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With