Meghashyam Sandeep V
Meghashyam Sandeep V

Reputation: 232

Rename nested keys in mongodb

I have a collection "user" as follows:

{
_id: "123",
"address": {
  "contact1":{
       "cell":"98765412345"
   },
  "contact2":{
       "cell":"98765412346"
   }
 }
}

I want to rename the field 'cell' to 'mobile' in all the nested objects contact1, contact2 and so on.

The following query works:

db.user.update({},{$rename:{'address.contact1.cell':'address.contact1.mobile'}})

I would ideally want all the nested objects to be updated. So I tried

db.user.update({},{$rename:{'address.$.cell':'address.$.mobile'}})

and this doesn't work. I searched for similar issues and all of them has nested arrays instead of maps (as in my case) and the answer that I got is that $rename doesn't work on nested arrays. I would want to know if its possible using a query instead of a script

Upvotes: 4

Views: 7177

Answers (2)

Chetan Nehete
Chetan Nehete

Reputation: 21

    { 
        "_id" : ObjectId("5c6f515bb910a41707811f56"), 
        "securityQuestions" : [
            {
                "sequenceNo" : "2", 
                "enabled" : "Y", 
                "questionText" : "what is your role?", 
                "questionNo" : "2"
            }, 
            {
                "sequenceNo" : "3", 
                "enabled" : "Y", 
                "questionText" : "what is your profile-dept ?", 
                "questionNo" : "3"
            }
        ]
    }

I was facing similar issue after trying something i got to know you have to set and unset the key.I was replacing questionNo to questionId. Refer the following solution

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

    db.collectionName.find({ "securityQuestions.questionNo": { "$exists": true } }).forEach(function(doc) {
        doc.securityQuestions.forEach(function(securityQuestions) {
            if ( securityQuestions.hasOwnProperty("questionNo") ) { 
                bulk.find({ "_id": doc._id, "securityQuestions.sequenceNo": securityQuestions.sequenceNo }).updateOne({
                    "$set": { "securityQuestions.$.questionId": securityQuestions.questionNo }
                });
                bulk.find({ "_id": doc._id, "securityQuestions.sequenceNo": securityQuestions.sequenceNo }).updateOne({
                    "$unset": { "securityQuestions.$.questionNo": 1 }
                });
                count += 2;

                if ( count % 500 == 0 ) {
                    bulk.execute();
                    bulk = db.collectionName.initializeOrderedBulkOp();
                }
            }
        });
    });

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

Upvotes: 0

Biswajit Panday
Biswajit Panday

Reputation: 837

db.testuser.update({},{$rename:{'address.contact1.cell':'address.contact1.mobile'}}, false, true);

the false is for upsert:false and the true is for multi: true. You need the multi:true to update all your records. and offcourse you have to manually go through with each different key. This will update all the cell under contact1 object to mobile not the cell under contact2 object. Otherwise you have to write some scripts.

Upvotes: 4

Related Questions