Search code examples
mongodbmongoosemongodb-querymongoose-schema

Change a specific field in multiple object of a sub document mongoose


I am trying to change a specific field in multiple objects of a sub-document to false but I am having issues with mongoose when I try to use $set to update the document.

This is the data structure.

[{
    name: 'Joe',
    card: [
      { type: 'visa', select: true},
      { type: 'masterCard', select: false},
      { type: 'unionPay', select: true},
    ]
},{
    name: 'Pascal',
    card: [
      { type: 'unionPay', select: false},
      { type: 'visa', select: true},
      { type: 'masterCard', select: false},
    ]
}]

execpted result

[{
    name: 'Joe',
    card: [
      { type: 'visa', select: false}, <--- was changed to false
      { type: 'masterCard', select: false},
      { type: 'unionPay', select: false}, <--- was changed to false
    ]
},{
    name: 'Pascal',
    card: [
      { type: 'unionPay', select: false},
      { type: 'visa', select: true},
      { type: 'masterCard', select: false},
    ]
}]

I currently wrote this query but it is not working as expected.

 this.user.model().findOneAndUpdate(
 { name: 'Joe },
  {
    card:{$set: { select: false },
  },
 );

What am I doing wrong?


Solution

  • Demo - https://mongoplayground.net/p/-ScRx2XpZ9E

    Use $[]

    The filtered positional operator $[] identifies the array elements that match the arrayFilters conditions for an update operation

    You can update 1 top-level index at one time

    db.collection.update(
     { name: "Joe" },
     { $set: { "card.$[c].select": false } },
     { arrayFilters: [ { "c.type": "visa" } ] }
    )
    

    Use db.collection.bulkWrite to make 2 queries in 1 go.

    db.collection.bulkWrite( [
       {
          updateOne : {
             "filter":{ name: "Joe" },
             "update": { $set: { "card.$[c].select": false } },
             "arrayFilters": [ { "c.type": "visa" } ]
          }
       },
       {
          updateOne : {
             "filter":{ name: "Joe" },
             "update": { $set: { "card.$[c].select": false } },
             "arrayFilters": [ { "c.type": "unionPay" } ]
          }
       }
    ])