Home > other >  Update more than one inner document in MongoDb
Update more than one inner document in MongoDb

Time:12-22

In my example project, I have employees under manager. Db schema is like this;

{
  "employees": [
    {
      "name": "Adam",
      "_id": "5ea36b27d7ae560845afb88e",
      "bananas": "allowed"
    },
    {
      "name": "Smith",
      "_id": "5ea36b27d7ae560845afb88f",
      "bananas": "not-allowed"
    },
    {
      "name": "John",
      "_id": "5ea36b27d7ae560845afb88g",
      "bananas": "not-allowed"
    },
    {
      "name": "Patrick",
      "_id": "5ea36b27d7ae560845afb88h",
      "bananas": "allowed"
    }
  ]
}

In this case Adam is allowed to eat bananas and Smith is not. If I have to give the permission of eating bananas from Adam to Smith I need to perform update operation twice like this:

db.managers.update(
    { 'employees.name': 'Adam' },
    { $set: { 'employees.$.bananas': 'not-allowed' } }
);

and

db.managers.update(
    { 'employees.name': 'Smith' },
    { $set: { 'employees.$.bananas': 'allowed' } }
);

Is it possible to handle this in a single query?

CodePudding user response:

You can use $map and $cond to perform conditional update to the array entries depending on the name of the employee. A $switch is used for potential extension of cases.

db.collection.update({},
[
  {
    "$set": {
      "employees": {
        "$map": {
          "input": "$employees",
          "as": "e",
          "in": {
            "$switch": {
              "branches": [
                {
                  "case": {
                    $eq: [
                      "$$e.name",
                      "Adam"
                    ]
                  },
                  "then": {
                    "$mergeObjects": [
                      "$$e",
                      {
                        "bananas": "not-allowed"
                      }
                    ]
                  }
                },
                {
                  "case": {
                    $eq: [
                      "$$e.name",
                      "Smith"
                    ]
                  },
                  "then": {
                    "$mergeObjects": [
                      "$$e",
                      {
                        "bananas": "allowed"
                      }
                    ]
                  }
                }
              ],
              default: "$$e"
            }
          }
        }
      }
    }
  }
])

Mongo Playground

CodePudding user response:

db.managers.update(
   {
      $or: [
         {"employees.name": "Adam"},
         {"employees.name": "Smith"}
      ]
   },
   {
      $set: {
         "employees.$[e].bananas": {
            $cond: [{ $eq: ["$e.name", "Adam"] }, "not-allowed", "allowed"]
         }
      }
   },
   {
      arrayFilters: [{ "e.name": { $in: ["Adam", "Smith"] } }]
   }
)
  • Related