Cynosure
Cynosure

Reputation: 161

MongoDB Multiple documents update with Positional Array index

Having a collections as below:

   [{
        "_id" : ObjectId("5ee111e541050ba2728adb3f"),
        "User" : "user1",
        "applications" : ["test1", "test2","test3"]
    },
    {
        "_id" : ObjectId("5ee111e541050ba2728adb40"),
        "User" : "user2",
        "applications" : ["test1", "test3","test2"]
    }]

Expected Output:

[{
        "_id" : ObjectId("5ee111e541050ba2728adb3f"),
        "User" : "user1",
        "applications" : ["test1", "test2Updated","test3"]
    },
    {
        "_id" : ObjectId("5ee111e541050ba2728adb40"),
        "User" : "user2",
        "applications" : ["test1", "test3","test2Updated"]
    }]

Used Below Query:

db.getCollection('testUser').update({"applications":"test2"},
{$set:{"applications.$[elem]":"Test2Updated"}},
{ "arrayFilters": [{ "elem": "test2" }], "multi": true })

Not working in MongoDB 3.4 Any Solutions to make it work on MongoDB 3.4 could be helpful

Upvotes: 1

Views: 61

Answers (1)

whoami - fakeFaceTrueSoul
whoami - fakeFaceTrueSoul

Reputation: 17915

As arrayFilters was only introduced after 3.6 you need to do it in two update operations, We can use .bulkWrite() to achieve this in one DB call.

Query :

db.collection.bulkWrite([
  /** First push `test2Updated` element to applications array where `test2` exists */
  {
    updateMany: {
      filter: { applications: "test2" },
      update: { $push: { applications: "test2Updated" } }
    }
  },
  /** Remove `test2` from applications */
  {
    updateMany: {
      filter: { applications: "test2" },
      update: { $pull: { applications: "test2" } }
    }
  }
]);

Note :

Since we can't use $set + $unset both on array field at same time we've split this into two ops.

Also if you've multiple test2 elements in same applications array use $pullAll to pull all of them out but you can't insert equivalent no.of test2Updated elements as you don't know how many test2's exist for a document in that case you need to individually read docs to code and update applications array(I guess this is not the case).

One other thing is test2Updated will not be pushed to same index at which test2 is but I guess this is not that important.

Upvotes: 1

Related Questions