skip to Main Content

I have a mongodb collection that looks like this:

{
     "_id" : ObjectId("60471bd482c0da3c0e70d26f"),
     "owner" : "John",
     "propAvailable" : {
        "val1" : true
    }
},
{
    "_id" : ObjectId("60471bd482c0da3c0e76523f"),
    "owner" : "Matt",
    "propAvailable" : {
    "val1" : {
       "val2" : true  
    }
}

I need to run an update query on this collection that will update the value of the ‘propAvailable’ key such that

db.collection('props').update({'owner' : 'John'} , {$set : {'propAvailable.val1.val2' : true}});

This query works if the document already looks like the second one but gives the error:
Cannot create field ‘val2’ in element {‘val1’: true} if the document format is the first one. Is there a way to write this query so that it overwrites the boolean ‘true’ and replaces it with the object {'val2' : true}

2

Answers


  1. You can use:

    db.collection.update({
      "owner": "John"
    },
    {
      $set: {
        "propAvailable.val1": {
          val2: true
        }
      }
    })
    

    To create val2: true inside propAvailable.val1 and replace its current content.

    As you can see working on the playground

    Login or Signup to reply.
  2. If you’re using Mongo version 4.2+ you can use pipelined updates to achieve this, like so:

    db.collection.updateMany({
      owner: "John"
    },
    [
      {
        $set: {
          "propAvailable.val1": {
            $mergeObjects: [
              {
                $cond: [
                  {
                    $eq: [
                      "object",
                      {
                        $type: "$propAvailable.val1"
                      }
                    ]
                  },
                  "$propAvailable.val1",
                  {}
                ]
              },
              {
                val2: true
              }
            ]
          }
        }
      },
    ])
    

    Mongo Playground

    For older mongo versions this is impossible to do in 1 query if objects potentially have additional fields under val1 you want to preserve. You will have to either read and update, or execute two different updates for each case.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search