Rahul Babu
Rahul Babu

Reputation: 790

Find and Replace NumberLong type field in mongodb

I am trying to update some NumberLong type value in one of my collection with some other NumberLong value. Below is my collection structure :

    {
    "_id" : ObjectId("55e57337d4c6cf80e68b1fe3"),
    "tenantId" : NumberLong(7),
    "refId" : NumberLong(20),
    "refIdentifierName" : "resourceInstanceId",
    "config" : {
        "contract" : {
            "contractLength" : "12 months",
            "startDate" : "2015-01-21T09:36:39+00:00",
            "billingFrequency" : "monthly",
            "margin" : 9,
            "endDate" : "2016-01-21T09:36:39+00:00"
        }

}

Lets say here i am trying to update all tenantId with value 7 to 8.

This is the script i am using :

 var cursor = db.resourceInstanceConfiguration.find();
while (cursor.hasNext()) {
  var x = cursor.next();
  x['tenantId'] = x['tenantId'].replace('7','8');
  db.resourceInstanceConfiguration.update({_id : x._id}, x);
}

Getting error : TypeError: Object NumberLong(6) has no method 'replace'

Upvotes: 3

Views: 1488

Answers (2)

Blakes Seven
Blakes Seven

Reputation: 50406

Seems some people were very quick to upvote another answer without realizing it cannot possibly work, nor is it a very good explanation.

The two problems here are that you basically need to "loop" the results in order to read the values you want to change and then write them back. This is probably best handled with "Bulk" operations and best done under the shell as a one of script.

The "next" problem is the BSON type information here is "sticky" and that you cannot simply change the value to an plain double in code and write it back. You need to actually "remove" the field completely from the document "before" you can write back a converted value.

Again the whole process lends well to bulk operations as follows:

var bulk = db.resourceInstanceConfiguration.initializeOrderedBulkOp(),
    count = 0;

db.junk.find({ 
    "$or": [
        { "tenantId": { "$type": 18 } },
        { "refId": { "$type": 18 } }
    ]            
}).forEach(function(doc) {
    print(doc.a.valueOf());
    bulk.find({ "_id": doc._id }).updateOne({
        "$unset": { "tenantId": "", "refId": "" }
    });
    bulk.find({ "_id": doc._id }).updateOne({
        "$set": { 
            "tenantId": doc.tenantId.valueOf(),
            "refId": doc.tenantId.valueOf()
        }
    });
    count += 2;

    if ( count % 1000 == 0 ) {
        bulk.execute();
        bulk = db.resourceInstanceConfiguration.initializeOrderedBulkOp();
    }

});

if ( count % 1000 != 0 )
    bulk.execute();

So you essentially $unset first to remove all trace for the BSON data for the field and the $set with the new value.

All values will then be a standard "double" or BSON type 1 as also confirmed by the $type operator.

Upvotes: 3

Kartikey Joshi
Kartikey Joshi

Reputation: 58

You can do achieve this by using the following query:

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
)

db.collectionName.update({<field>:<value>},{$set:{<field>:<New Value>}},<upsert>,<multi>);

Upvotes: 4

Related Questions