Change document value from string to ObjectId using Update Query
Asked Answered
R

5

8

I need to Update the Value of Profession_id from string to ObjectId for all document in a mongodb collection.

My Collection Profession is (Here I pasted only 2 Documents, in real I'm having more than 10K Documents)

{
    "_id" : ObjectId("575845a713d284da0ac2ee81"),
    "Profession_id" : "575841b313d284da0ac2ee7d",
    "Prof_Name" : "Chief Officer"
}

{
    "_id" : ObjectId("575845d213d284da0ac2ee82"),
    "Profession_id" : "575841b313d284da0ac2ee7d",
    "Prof_Name" : "Executive Officer"
}

Kindly assist me how to update the value in MongoDB.

Reinhart answered 9/6, 2016 at 6:4 Comment(0)
F
8

We need to iterate over the snapshot() of our documents and update each document using the $set update operator. And to do this we use bulk operation for maximum efficiency.

Starting from MongoDB 3.2, we need to use the bulkWrite() method

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

// Clean up queues
if (requests.length > 0)
    db.collection.bulkWrite(requests);     

From MongoDB 2.6 to 3.0 you need to use the now deprecated Bulk API and it associated method.

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

var cursor = db.collection.find({}, { "Profession_id": 1 }).snapshot()

cursor.forEach(function(document) { 
    bulk.find( { "_id": document._id } ).updateOne( {
        "$set: { "Profession_id": ObjectId(document.Profession_id) }
    } );
    count++;
    if (count % 1000 === 0) {
        // Execute per 1000 operations and re-init
        bulk.execute();
        bulk = db.collection.initializeUnorderedBulkOp();
    }
});

// Clean up queues
if (count > 0)
    bulk.execute();
Federico answered 9/6, 2016 at 6:23 Comment(1)
I had to filter by type like let cursor = db.collection.find({ "TheString_id" : { $type : "string" } }, { "TheString_id": 1 }).snapshot(); to avoid some errors on partial updatesMeehan
B
4

Starting from 4.0, you can use $toObjectId of aggregation pipleline. Combined with $set, you can do this (https://mongoplayground.net/p/YFqRLMvEpCG):

db.collection.update({},
[
  {
    $set: {
      "Profession_id": {
        $toObjectId: "$Profession_id"
      }
    }
  }
],
{
  "multi": true
})
Brainstorming answered 22/8, 2021 at 8:1 Comment(0)
M
1

You can just do this:

db.collectionName.find({
    id: {
        $type: 2
    }
}).forEach (doc => {
    db.stringToObject.update({
        _id: doc._id
    }, {
        "$set": {
            "Profession_id": ObjectId(doc.Profession_id) 
        } 
    })
})
Maiamaiah answered 23/10, 2018 at 14:3 Comment(0)
S
0

I have used below code for mongo 4.0

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

// Clean up queues
if (requests.length > 0)
    db.collection.bulkWrite(requests);
Scarron answered 23/10, 2018 at 13:18 Comment(0)
G
0

Another solution is a pretty simple aggregation pipeline:

[ 
  {
      $addField: {
         yourfield:ObjectId("$yourField")
      }
  }, 
  {
    $out:"yourcollection"
  } 
]
Grati answered 21/9, 2023 at 15:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.