Let's say I have the following data document in Mongo:
{ id: '1',
collaborators: [
{ name: "name 1",
email: "email 1",
rating: null
},
{ name: "name 2",
email: "email 2",
rating: null
}],
social: [
{ type: "type A",
message: "message A",
response: false
},
{ type: "type B",
message: "message B",
response: false
}]
}
and I need to update both email 1
and type B
objects in their respective arrays from the returned data.
I know I can run a positional operator update in two separate calls i.e. something like:
await model.findOneAndUpdate({_id: 1, collaborators.email: "email1"}, {$set: { "collaborators.$.rating: 5"}})
await model.findOneAndUpdate({_id: 1, social.type: "typeB"}, {$set: { "social.$.response: true"}})
and I could probably use bulkWrite
to make it more efficient, as I'll end up with a lot more of these in production, but can I just run one query to update both arrays ?
Credit goes to @joe for bringing up the idea of using arrayFilters
You can specify matched element position through the usage of arrayFilters
and update the referenced element.
db.collection.update({},
{
$set: {
"collaborators.$[c].rating": 5,
"social.$[s].response": true
}
},
{
arrayFilters: [
{
"c.email": "email 1"
},
{
"s.type": "type B"
}
]
})
One of the side notes is that you may want to consider refactoring the schema to separate collaborators
and social
into different documents/collections. It could be contradicting your requirement of minimizing db calls but they seem like independent information from the context I observed in the post. Separating them can bring benefits of simpler code and potential performance boost through indexing.