felipeecst
felipeecst

Reputation: 1415

Replace Embedded Document using Mongo C# 2.0 driver

I have a document that have a embedded array of units, like this:

{
    "_id" : ObjectId("5807c22e959ca231f0c48a75"),
    "Code" : "Value",
    "Units" : [ 
        {
            "_id" : ObjectId("5807cc08959ca331f09c530e"),
            "Code" : "Foo",
            "Label" : "Foo"
        },
        {
            "_id" : ObjectId("5807cc08959ca331f09c530e"),
            "Code" : "Bar",
            "Label" : "Bar"
        },
    ]
}

I want to find a unit by its id and replace it with a new document. How could I do that using the Mongo C# Driver 2.0?

Thanks in advance!

Upvotes: 2

Views: 1088

Answers (2)

pieperu
pieperu

Reputation: 2762

Assuming your models in C# look like this:

public class UnitLog
{
    [BsonRepresentation(BsonType.ObjectId)]
    [BsonId]
    public string Id { get; set; }

    public string Code { get; set; }

    public List<Unit> Units { get; set; }
}

public class Unit
{
    [BsonRepresentation(BsonType.ObjectId)]
    [BsonId]
    public string Id { get; set; }

    public string Code { get; set; }

    public string Label { get; set; }
}

You could use a PullFilter to pull an item from an embedded array. Here is an example with the MongoDb 2.0 driver:

var mainDocumentId = "5807c22e959ca231f0c48a75";//Your containing document's Id
var arrayItemId = "5807cc08959ca331f09c530e";//Id for array item with Code=foo

var pullFilter = Builders<UnitLog>.Update.PullFilter(
        x => x.Units,
        x => x.Id == arrayItemId 
    );

//Note that you would use Collection.UpdateManyAsync()  
//if you expected more than one item to be updated/pulled
var result = await Collection.UpdateOneAsync(
        x => x.Id == mainDocumentId,
        pullFilter
    ).ConfigureAwait(false);

To identify items in an embedded array you would use $elemMatch for this

ElemMatch MongoDb documentation

ElemMatch can be found

Builders<UnitLog>.Filter.ElemMatch 

And can be used in conjunction with $set to update individual properties of embedded documents, identified using $elemMatch.

Look into AddToSet, you may find this useful as it adds an item to an array unless the item exists already

AddToSet MongoDb documentation

AddToSet can be found

Builders<UnitLog>.Update.AddToSet

Upvotes: 3

felipeecst
felipeecst

Reputation: 1415

Thanks guys. From your answers, I came up with the following solution:

var mainDocumentId = "5807c22e959ca231f0c48a75";
var arrayItemId = "5807cc08959ca331f09c530e"; //Id for foo

var unit = new Unit(...)
var filter = Builders<UnitType>.Eq(o => o.Id, mainDocumentId); // optional
filter &= Builders<UnitType>.Filter.ElemMatch(o => o.Units, o => o.Id == arrayItemId);
var update = Builders<UnitType>.Update.Set(o => o.Units[-1], unit);

collection.UpdateOne(filter, update);

Upvotes: 6

Related Questions