Search code examples
c#mongodbmongodb-.net-driver

Increment sub document field in a MongoDb Database


I have this model:

{
    id: long,
    items: [{
        itemId: long,
        amount: decimal
    }]
 }

edit: I need to increment the amount value depending on id and itemId.

My query:

var query = Builders<model>.Filter.And(
    Builders<model>.Filter.Eq(_ => _.id, xxx),
    Builders<model>.Filter.ElemMatch(_ => _.items, _ => _.itemId == yyy)
);

var update = Builders<modelItem>.Update.Inc(_ => _.amount, incrementalAmount);

But i don't know how to execute the query/update.

this.Collection.FindOneAndUpdate(query, update);

Of course i can't use this UpdateDefinition because i must use builder<'model> instead of builder<'modelItem>, but how to increment the sub property ?


Solution

  • I finally found how to increment the sub document:

    The query stay the same, and i use the operator $ to update the appropriate array item:

    Builders<Model>.Update.Inc("Items.$.Amount", incrementValue);
    

    For a little bit more complicated increment, Im using the arrayfilter:

    var caf = new BsonDocumentArrayFilterDefinition<ModelItem>(new MongoDB.Bson.BsonDocument("caf.ItemId", new MongoDB.Bson.BsonDocument("$eq", YYYY)));
    var oaf = new BsonDocumentArrayFilterDefinition<ModelItem>(new MongoDB.Bson.BsonDocument("oaf.ItemId", new MongoDB.Bson.BsonDocument("$ne", YYYY)));
    
    var query = Builders<Model>.Filter.Eq(_ => _.Id, XXXX);
    
    var update = Builders<Model>.Update.Combine(
        Builders<Model>.Update.Inc("Items.$[caf].Amount", incrementValue),
        Builders<Model>.Update.Inc("Items.$[oaf].Amount", -incrementValue)
    );
    
    await this.Collection.UpdateManyAsync(query, update, new UpdateOptions()
    {
        ArrayFilters = new List<ArrayFilterDefinition>() { caf, oaf}
    });