Search code examples
c#mongodbmongodb-querymongodb-.net-drivermongodb-update

MongoDB .NET Driver - Update Item in Set


I've got this entity:

internal record OrderBookEntity
{
    [BsonId]
    public required AssetDefinition UnderlyingAsset { get; init; }
    
    public required List<OrderEntity> Orders { get; init; }
}

which leads to this sort of document:

{
    _id: {
        Class: 0,
        Symbol: 'EURUSD'
    },
    Orders: [
        {
            _id: 'a611ffb1-c3e7-43d6-8238-14e311122125',
            Price: '-10.000000101',
            Amount: '30.000000003',
            OrderAction: 1,
            EffectiveTime: ISODate('2022-10-14T06:33:02.872Z')
        },
        {
            _id: 'a611ffb1-c3e7-43d6-8238-14e311122126',
            Price: '-10.000000101',
            Amount: '30.000000003',
            OrderAction: 1,
            EffectiveTime: ISODate('2022-10-14T06:33:08.264Z')
        }
    ]
}

I can add and remove from the Orders set without updating the whole document with:

Builders<OrderBookEntity>.Update.AddToSet(...);
Builders<OrderBookEntity>.Update.Pull(...);

I can't, however, see a way to modify one of those in place.

How would I go about changing the Amount on saying a611ffb1-c3e7-43d6-8238-14e311122125 without having to read the document, modify the collection, and update the whole thing, or just pulling and reading the order... Neither of which seems particularly performant.


Solution

  • You can work with FieldDefinition by providing the field to be updated in string instead of Func expression.

    MongoDB query

    db.collection.update({
      "Orders._id": "a611ffb1-c3e7-43d6-8238-14e311122125"
    },
    {
      $set: {
        "Orders.$.Amount": "100"
      }
    })
    

    Demo @ Mongo Playground

    MongoDB .NET Driver syntax

    var filter = new BsonDocument 
    { 
        { "Orders._id", "a611ffb1-c3e7-43d6-8238-14e311122125" } 
    };
    var update = Builders<OrderBookEntity>.Update.Set("Orders.$.Amount", /* value */);
    
    UpdateResult result = await _collection.UpdateOneAsync(filter, update);
    

    Demo

    enter image description here