0

There are so many questions and answers regarding this subject but why not make it simple.

Branch schema

const Branch = new Schema({
    name:    { Type: String },
    address: {
                 houseNumber: { Type: String },
                 street:      { Type: String },
                 city:        { Type: String }
             }
})

Client schema

const Client = new Schema({
    ...,
    ...,
    branches: [ branch ] // BRANCH SCHEMA IS SUB DOCUMENTED HERE
})

I know how to $push and $pull branch from branches array.
What I need is to UPDATE the ENTIRE branch object inside branches array, NOT JUST ONE FIELD like I found in so many answers and YES I would like to have back the modified document.

let clientId = req.body.clientId;
let branch   = req.body.branch;

Client
.findOneAndUpdate(
    { 
        "_id": clientId,
        "branches._id": branch._id
    },
    {
        OPTION 1 // MODIFIED ONLY THE FIRST ITEM (object) IN THE ARRAY
        "$set:" { "branches.$": { branch } }

        OPTION 2 // MODIFIED EVERY ITEM (object) IN THE ARRAY
        "$set:" { "branches.$[]": { branch } }
        
        STILL NO GOOD... HOW TO SOLVE THIS ??        
                                
    }
)
.then(client => {
    
    WHAT SHOULD I DO HERE IN ORDER TO UPDATE AN ENTIRE BRANCH ??

})
.catch(e => console.log(`error Client.findOne() ${e}`))
user12163165
  • 555
  • 8
  • 12
  • Does this answer your question? [Replacing embedded document in array in MongoDB](https://stackoverflow.com/questions/9200399/replacing-embedded-document-in-array-in-mongodb) – Jiří Pospíšil Jul 21 '20 at 08:02
  • NO, in the provided link there are 2 examples, the first example always modifies the first object in the array and if I change `"branches.$"` to `branches.$[]` it modifies all the objects inside the array. the second example is no good for my case. thanks @Jiří – user12163165 Jul 21 '20 at 08:34
  • The first example does't always modify the first object, it modifies the first *matching* object within that array. Have a look at the [documentation](https://docs.mongodb.com/manual/reference/operator/update/positional/index.html). – Jiří Pospíšil Jul 21 '20 at 08:47
  • @Jiří, I updated my question with the examples from the link you provided, where is my mistake then? – user12163165 Jul 21 '20 at 08:49

2 Answers2

0

You can use mongoose arrayFilters to achieve what you want:

Client
.findOneAndUpdate(
    { 
        "_id": clientId,
        "branches._id": branch._id
    },
    {
        "$set:" { "branches.$[elem]": { branch } }                                
    },
    {
        arrayFilters: [ { 'elem._id': branch._id } ]
    }
)
.then(client => {

})
.catch(e => console.log('error Client.findOne() + e))

MahanTp
  • 744
  • 6
  • 16
0

Okay, here is how I did it..

let clientId = req.body.clientId;
let branch   = req.body.branch;

Client
.findOne({ _id: clientId })
.then(client => {
         
      // finding the index
      const elementIndex = client.branches.findIndex(element => element._id.toString() === branch._id.toString());

      // creating new array and assigning the branches array to it using spread syntax 
      let newBranches = [ ...client.branches ];

      // adding the branch I need to update to newBranches array (at the same index)
      newBranches[elementIndex] = branch;

      // replacing branches array with the new one, again using spread syntax
      client.branches = [ ...newBranches ];

      // saving
      client.save();
})
.catch(e => console.log(`error Client.findOne() ${e}`))

enjoy!

user12163165
  • 555
  • 8
  • 12