Reputation: 1415
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
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
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