1

Sounds messy, I know.
The document I'm modifying is structured like this:

{
   "_id":12345,
   "name":"harold",
   "basicData":{
      "devices":[
         {
            "id":7654,
            "relatedJson":{
               "make":"sony",
               "equipmentID":"asdf"
            }
         },
         {
            "id":9493
         }
      ],
      "car":"toyota"
   }
}

I can't quite get the code right. This is what I have:

db.serviceAgreement.updateMany({"basicData.devices.relatedJson.equipmentID": {$exists: true}},
    [
        {
            $set: {
                "basicData.devices": {
                    $map: {
                        input: "$basicData.devices", in: {
                            $mergeObjects: ["$$this.relatedJson",
                                {equipmentId: "$$this.relatedJson.equipmentID",}]
                        }
                    }
                }
            }
        },
        {
            $unset: "basicData.devices.relatedJson.equipmentID"
        }

    ])

So my understanding of this script is that I'm calling $set to set the field basicData.devices, then I'm setting it to that same list, but before I do that I'm merging the documents relatedJson and a new document {equipmentId : "$$this.relatedJson.equipmentID",} which has the value equipmentId set to the same value as the equipmentID in the relatedJson object.
Then, I'm replacing the relatedJson document with the newly created equipmentId (not my intention).
And finally, deleting the original equipmentID - which doesn't actually exist any more because I've replaced the whole relatedJson object.

How can I insert the new equipmentId into the relatedJson object, instead of replacing it entirely.

I have tried variations of the above script that do all sorts of things, inserting a copy of relatedJson into itself, inserting a copy of devices into relatedJson, deleting everything inside devices, but I can't get it to do what I want.
I feel I'm close to a solution, and maybe I need to modify the $input: but I can't figure out how, or maybe my approach is totally wrong.
Any help would be greatly appreciated.

The end result should be the same document, but relatedJson.equipmentID should be renamed relatedJson.equipmentId (with a lower-case 'd' at the end);

2
  • 1
    can you add what is your expected output? I'm not sure I understood it Commented Sep 21, 2022 at 13:04
  • I want to rename relatedJson.equipmentID to relatedJson.equipmentId (lower case 'd' at the end) so the document should remain the same except for that change. Commented Sep 21, 2022 at 13:11

1 Answer 1

1

You're close, you just had some syntax issues.

The update should look like this:

db.collection.updateMany({"basicData.devices.relatedJson.equipmentID": {$exists: true}},
[
  {
    $set: {
      "basicData.devices": {
        $map: {
          input: "$basicData.devices",
          in: {
            $mergeObjects: [
              "$$this",
              {
                $cond: [
                  {
                    $ne: [
                      "$$this.relatedJson",
                      undefined
                    ]
                  },
                  {
                    relatedJson: {
                      $mergeObjects: [
                        "$$this.relatedJson",
                        {
                          equipmentId: "$$this.relatedJson.equipmentID"
                        }
                      ]
                    }
                  },
                  {}
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    $unset: "basicData.devices.relatedJson.equipmentID"
  }
])

Mongo Playground

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

6 Comments

So you're adding a condition saying if the document is != relatedJson then do nothing? (I'll google all this later, just curious if my interpretation is right).
Basically yes.and obviously the additional syntax changes.
Hi again, I'm having trouble getting my head around how the $cond and $ne part of the script works. The way I'm understanding it is like $cond[ <boolean condition>, <do if true>, <do if false>] but then the $ne part I'm not getting, does it say "if serviceAgreementStatus is not equal to undefined" ? The mongodb docs don't explain that syntax you are using. Any chance you could explain it?
Yes, essentially if "relatedJson" does not exist ( like the in the second device in your sample ) i don't want to create an empty object for it. so basically i tell the "$cond" if this object does not exists just merge with the empty object {}. specifically the $ne part just tells mongo if this field is not undefined meaning "relatedJson" exists, it's basically a way to replace the "$exists" operator which is not part of the aggregation expression language.
Thank you! You've helped my understanding of these scripts immensely! I've had a lot of trouble getting my head around this stuff.
|

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.