Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a field to an array using update operation

In Mongo, how do you convert a field to an array containing only the original value using only the update operation?

Given a document:

{
  "field": "x"
}

Then one or more update operation(s):

db.items.update(...)

Should result in:

{
    "field": ["x"]
}
like image 308
driangle Avatar asked Oct 18 '25 13:10

driangle


1 Answers

MongoDB does not currently allow you to refer to the existing value of a field within an update type of operation. In order to make changes that refer to the existing field values you would need to loop the results. But the array conversion part is simple:

db.collection.find().forEach(function(doc) {
    db.collection.update(
        { _id: doc._id },
        { "$set": { "field": [doc.field] } }
    );
})

Or even better with bulk update functionality in MongoDB 2.6:

var batch = [];
db.collection.find().forEach(function(doc) {
     batch.push({
        "q": { _id: doc._id },
        "u": { "$set": { "field": [doc.field] } }
    });

    if ( batch.length % 500 == 0 ) {
        db.runCommand({ "update": "collection", "updates": batch });
        batch = [];
    }
});

if ( batch.length > 0 )
    db.runCommand({ "update": "collection", "updates": batch });

Or even using the new Bulk API helpers:

var counter = 0;
var bulk = db.collection.initializeUnorderedBulkOp();
db.collection.find().forEach(function(doc) {
     bulk.find({ _id: doc._id }).update({
         "$set": { "field": [doc.field] } 
    });
    counter++;

    if ( counter % 500 == 0 ) {
        bulk.execute();
        bulk = db.collection.initializeUnorderedBulkOp();
        counter = 0;
    }
});

if ( counter > 0 )
    bulk.execute();

Both of those last would only send the updates to the server per every 500 items or whatever you want to tune it to under the 16MB BSON limit. All updates are still performed individually, but this removes a lot of write/confirmation traffic from the overall operation and is much faster.

like image 67
Neil Lunn Avatar answered Oct 20 '25 08:10

Neil Lunn