6

We have documents that were originally stored using the StringObjectIdGenerator type for _id. Newer data will be saved using the default ObjectIdGenerator. We would like to be able to migrate the existing data by converting the _id to the new data type. Is this possible?

3 Answers 3

7

Yes, it's possible to change data type, we need to find all documents with string id, using the iterator we can clone a document by changing its _id, after cloning we just need to delete the old document.

Below is for a small document, for large collection you may need to use db.collection.initializeUnorderedBulkOp() for bulk insert/delete

db.i.find({_id : {$type : 2}}). //find all string _id
    forEach(function(d){
        var id = ObjectId(d._id); //_id to ObjectId
        var oldId = d._id; // _id
        d._id = id; 
        db.i.insert(d); // clone doc with new Id
        db.i.remove({ _id : oldId }); // delete old doc
        }
    )

Example

> db.i.insertMany([{},{},{},{_id : "4a5ec389fee4c182f509f3ba"}, {_id : "4b5ec389fee4c182f509f3ba"}])
{
    "acknowledged" : true,
    "insertedIds" : [
        ObjectId("5a5ec9edfee4c182f509f3c9"),
        ObjectId("5a5ec9edfee4c182f509f3ca"),
        ObjectId("5a5ec9edfee4c182f509f3cb"),
        "4a5ec389fee4c182f509f3ba",
        "4b5ec389fee4c182f509f3ba"
    ]
}


> db.i.find()
{ "_id" : ObjectId("5a5ec9edfee4c182f509f3c9") }
{ "_id" : ObjectId("5a5ec9edfee4c182f509f3ca") }
{ "_id" : ObjectId("5a5ec9edfee4c182f509f3cb") }
{ "_id" : "4a5ec389fee4c182f509f3ba" }
{ "_id" : "4b5ec389fee4c182f509f3ba" }


> db.i.find({_id : {$type : 2}}).
... forEach(function(d){
... var id = ObjectId(d._id); 
... var oldId = d._id; 
... d._id = id; 
... db.i.insert(d); 
... db.i.remove({ _id : oldId }); 
... }
... )


> db.i.find()
{ "_id" : ObjectId("5a5ec9edfee4c182f509f3c9") }
{ "_id" : ObjectId("5a5ec9edfee4c182f509f3ca") }
{ "_id" : ObjectId("5a5ec9edfee4c182f509f3cb") }
{ "_id" : ObjectId("4a5ec389fee4c182f509f3ba") }
{ "_id" : ObjectId("4b5ec389fee4c182f509f3ba") }
> 
Sign up to request clarification or add additional context in comments.

1 Comment

the remove statement should be above the insert statement, as inserting before removing existing document on indexed collection can result in duplicate index error i.e. unique index.
1
db.inventries.find({ _id: { $type: 2 } }).forEach(function (d) { var id = ObjectId(d._id); var oldId = d._id; d._id = id; db.inventries.insert(d); db.inventries.remove({ _id: oldId }); } )


// change inventries => your collection name

hit above commend in mongodb console

Comments

-1
db.getCollection('Files').find({"_id":{"$exists":true}}).forEach(function(x){ 
    let id;
    try {     
      id = new ObjectId(x._id);  
    } 
    catch (err) {     
     id = new ObjectId();  
   } 
  db.Files.update( { "_id": x._id}, { $set: { _id:id } } );  
 }

)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.