2

I have a mongodb collection with a number of objects like this:

{
 "_id" : "1234", 
 "type" : "automatic", 
 "subtypes" : [
    {
     "_id" : "dfgd",
     "name" : "test subtype", 
     "subjetRequired" : true,
    },
    {
     "_id" : "dfgd",
     "name" : "test subtype2", 
     "subjetRequired" : false,
    }
  ],
 "anotherField" : "some value"
}

As you can see, one of the keys in the subtypes array is incorrectly spelled - "subjetRequired" instead of "subjectRequired".
I want to correct that key name. How can I do that.
I'll preface this by saying I've not worked with mongodb very much in the past.
After a lot of researching, the best I could come up with is the following (which doesn't work):

function remap(doc) {
     subtypes = doc.subtypes;
     var count = 0;
     subtypes.forEach(function(subtype){
         db.taskType.update({"_id": subtype._id}, {
             $set: {"subtypes.subjectRequired" : subtype.subjetRequired},
             $unset: {"subtypes.subjetRequired": 1}
         });
     }
     )
}

db.taskType.find({"subtypes.subjetRequired":{$ne:null}}).forEach(remap);

This doesn't work.
I know the loop is correct, as if I replace the other logic with print statements I can access and print the fields who's names I want to modify.
What am I doing wrong here?

2
  • You can use the same technique shown in this post, but use the $rename update operator (instead): stackoverflow.com/questions/19945924/… Commented Aug 24, 2022 at 12:44
  • 1
    Noted that the documentation says that the update on arrays with sub-documents do not support the $rename update operation. Commented Aug 26, 2022 at 10:14

2 Answers 2

1

You can use this update and avoid using any code, it's also stable so you can execute it multiple times with no fear.

db.collection.updateMany({
  "subtypes.subjetRequired": {
    $exists: true
  }
},
[
  {
    $set: {
      subtypes: {
        $map: {
          input: "$subtypes",
          in: {
            $mergeObjects: [
              "$$this",
              {
                subjectRequired: "$$this.subjetRequired",
                
              }
            ]
          }
        }
      }
    }
  },
  {
    $unset: "subtypes.subjetRequired"
  }
])

Mongo Playground

Sign up to request clarification or add additional context in comments.

Comments

1

I could modify your loop to override the whole array of subtypes:

function remap(doc) {
  correctSubtypes = doc.subtypes.map(({ subjetRequired, ...rest }) => ({
    ...rest,
    subjectRequired: subjetRequired,
  }));
  var count = 0;
  db.taskType.findByIdAndUpdate(doc._id, {
    $set: {
      subtypes: correctSubtypes,
    },
  });
}

1 Comment

This looks good for small objects, but the ones I'm dealing with can have hundreds of fields.

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.