Ryne
Ryne

Reputation: 1415

Is something missing in these positional arguments for nested array updates?

I have a document that has 3 nested arrays. I'm updating the second nested array with this function:

// Append $set key
for(var key in u)
  updates["scopes.$[].sections.$." + key] = u[key];

Proposal.findOneAndUpdate({
  "scopes.sections._id": req.body.id // sectionId
}, {
  $set: updates
}, { new: true })
.then(response => {
  console.log(response);
})
.catch(error => {
  console.log(error);
});

I use a similar function to update the first nested array- scopes. That is working properly and updates the scope that matches. But for the second nested array only the first element of the array is being updated. I logged the id and the correct param is being passed in the req.body.

Is there something I'm missing in the update key- scopes.$[].sections.$.key ?

Edit with sample document and logs-

_id: 6079c199c5464b6296b113f6
name: ""
status: "outstanding"
hasAutomaticThreshold:false
isDiscount:true
discount: 0
discountPercentage: 0
taxRate: 9
companyId: 606f5e179cc0382ad6aacd84
clientId: 6070fa06dd505146ccfac9ec
projectId: 60736ed48fb2c869e0c9b33d
author: 606f5e259cc0382ad6aacd86
scopes: Array
  0:Object
    title: ""
    isExpanded: true
    _id: 6079c199c5464b6296b113f7
    sections:Array
      0:Object
        title:"Section One"
        description:""
        isExpanded:false
        _id: 6079c199c5464b6296b113f8
        items: Array
      1:Object
        title:""
        description:""
        isExpanded:false
        _id: 6079c1f8d3176462c0840388
        items: Array

And this is what the logged req.body.id and updates object looks like:

6079c1f8d3176462c0840388 // ID
{ 'scopes.$[].sections.$.title': 'Section One' }

Upvotes: 1

Views: 32

Answers (1)

turivishal
turivishal

Reputation: 36124

The positional $ operator will update single position, you need to use arrayFilters $[<identifier>],

// Append $set key
for(var key in u)
  updates["scopes.$[].sections.$[s]." + key] = u[key];

Proposal.findOneAndUpdate(
  { "scopes.sections._id": req.body.id },
  { $set: updates },
  { 
    arrayFilters: [{ "s._id": req.body.id }],
    new: true
  }
)
.then(response => {
  console.log(response);
})
.catch(error => {
  console.log(error);
});

Playground

Upvotes: 1

Related Questions