The short answer here is no, at least if you want to match and not just set specific elements (rather than looking to match multiple elements), something like this:
> db.students.findOne()
{
"_id" : "abcd",
"arrayItems" : [
{
"name" : "Peter",
"age" : 23,
"profession" : "Student"
},
{
"name" : "Paul",
"age" : 80,
"profession" : "Student"
},
{
"name" : "Mary",
"age" : 45,
"profession" : "CEO"
}
]
}
> db.students.update(
{ "_id" : "abcd"},
{ $set: {"arrayItems.0.age": 27, "arrayItems.1.age" : 23 }}
);
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.students.findOne()
{
"_id" : "abcd",
"arrayItems" : [
{
"name" : "Peter",
"age" : 27,
"profession" : "Student"
},
{
"name" : "Paul",
"age" : 23,
"profession" : "Student"
},
{
"name" : "Mary",
"age" : 45,
"profession" : "CEO"
}
]
}
Unfortunately, unlike this simple test, with real usage there is no guarantee that the array you are updating has the structure you think it does, even if you fetch it immediately beforehand there is always the chance that someone updates between the read and your update.
In order for this to work you need SERVER-1243 to be implemented, and that is not currently planned for an imminent release. Here is the current statement on that lack of capability from MongoDB (as of Jun 2016) from that ticket:
MongoDB appreciates the challenge of maintaining applications
utilizing schemas with large arrays, especially with respect to
updating many or all array elements, and we very much recognize the
interest from the community around this ticket.
Unfortunately, to implement such a major feature there are serious
requirements:
- a specification for new language features (like update modifiers or expressions), since we cannot break existing uses
- should be included with support to match all array elements, as well was those matching a query
- requests for support to update the last element(s) could be considered.
- must support all existing update modifiers (correctly, and in a non-backwards-breaking way) $rename, $set, $unset, $pull, $push,
$bit...
- must work efficiently with all arrays, including those having thousands of elements
- cannot change current update semantics or behaviors which existing applications and deployments depend on (non-backwards-breaking).
In summary, adding this as a new feature, or improvement, is not
trivial. It will require resources which are currently working on
other projects, and in short is a matter of prioritization over other
parts of the whole server.
As you can infer from the age of the ticket and the lengthy discussion, this has come up many times and there are plenty of workarounds in the ticket and elsewhere but (as yet) there is no built-in method to achieve this.