As mentioned, the main issue here is with updates on multiple elements with the positional operator as recorded in this long standing issue: http://jira.mongodb.org/browse/SERVER-1243
The basic case therefore is no single execution can do this, so in order to process for multiple array elements you need some method of determining how many elements you need to update and process one update statement per each element.
A simplified approach to this is generally using Bulk Operations to process what ends up being "mulitple" update operations as a single request and response to the server:
var bulk = db.collection.initializeOrderedBulkOp(),
count = 0;
db.collection.find({ "name": "John Doe", "adds.status": "PENDING" }).forEach(function(doc) {
doc.adds.filter(function(add){ return add.status = "PENDING" }).forEach(function(add) {
bulk.find({ "_id": doc._id, "adds.status": "PENDING" }).updateOne({
"$set": { "adds.$.status": "APPROVED" }
});
count++;
// Execute once in 1000 statements created and re-init
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp();
}
});
});
// Execute any pending operations
if ( count % 1000 != 0 )
bulk.execute();
If your updated documents is quite small, or indeed only a single document then you can forgo the count
check and simply append all bulk updates within the required loops and just execute once at the end of all loops.
A longer explaination and alternates can be found on How to Update Multiple Array Elements, but all come down to different approaches to matching the element to update and processing a positional $
update mutliple times, for either each document matched or until there are no more modified documents returned.