MongoDB update multiple sub documents inside array, each according to a condition I have a document like this:

{
    wid: 1,
    items: [
        {nid: 1, sent: 900},
        {nid: 2, sent: 12},
        {nid: 3, sent: 0},
        {nid: 4, sent: 1}
    ]
}


Now consider I want to update this document with an object I compute from somewhere else:

# All for wid:1, a mapping of nid:sent
# These values should be added to values already in the DB
{
    2: 37,
    3: 58,
    4: 172
}




so after the update, I want to have something like:

{
    wid: 1,
    items: [
        {nid: 1, sent: 900},
        {nid: 2, sent: 49},
        {nid: 3, sent: 58},
        {nid: 4, sent: 173}
    ]
}


Is there anyway to do this with only one update query?

What I know works->

db.test.update_one({wid: 1, 'items.nid': 2}, {$inc: {'items.$.sent': 37}})
db.test.update_one({wid: 1, 'items.nid': 3}, {$inc: {'items.$.sent': 37}})
db.test.update_one({wid: 1, 'items.nid': 4}, {$inc: {'items.$.sent': 172}})


But that's O(n) update queries issued and this is really contradicting all reasons I chose to stick to MongoDB.

Thanks!
Use the arrayFilters property:

db.getCollection("test").updateOne(
    {
        "wid": 1
    },
    {
        $inc: {
            "items.$[aa].sent": 37,
            "items.$[bb].sent": 58,
            "items.$[cc].sent": 172
        }
    },
    {
        upsert: false,            
        arrayFilters: [
            { "aa.nid": 2 },
            { "bb.nid": 3 },
            { "cc.nid": 4 }
        ]
    }
);


For each named identifier you create (aa, bb, cc in the example), should be created a matching document in the arrayFilters array.