Updating an embedded document in MongoDB with official C# driver
If I have a Company collection which contains embedded Divisions:
{
"_id": 1
"_t": "Company",
"Name": "Test Company"
"Divisions": [
{
"_id": 1
"_t": "Division",
"Name": "Test Division 1"
},
{
"_id": 2
"_t": "Division",
"Name": "Test Division 2"
}
]
}
What is the best way to save/update an entire Division when using the official 10gen C# driver? (The latest 0.9 release.)
I'm using Update.AddToSetWrapped to add Divisions, and that works fine, but I'd also like to be able to update documents depending on their _id.
For example, if I define the following Update method:
public void UpdateDivision(IDivision division)
{
var mongo = MongoServer.Create(_connectionString);
var database = mongo.GetDatabase(_databaseName);
var query = Query.EQ("_id", division.CompanyId);
var update = Update.AddToSetWrapped("Divisions", division);
database.GetCollection<Company>("Company")
.Update(query, update, UpdateFlags.Upsert, SafeMode.True);
}
and call it like so:
var division = GetDivisionById(1);
division.Name = "New Name";
UpdateDivision(division);
Then a new instance of Division will be added to the set, beca开发者_运维问答use although the "_id" is still 1, the Name is different, and therefore it is a unique document.
So what is there a good way to update a whole embedded document?
Until I come up with a better solution I am going to first $pull
the original Division and then $addToSet
with the modified Division. That works but is obviously not ideal as it performs two separate updates.
You could use the positional array modification feature of MongoDB to update an entire division in the array at once as follows:
var division = GetDivisionById(1);
division.Name = "New Name";
// change any other properties of division you want
collection.Update(
Query.EQ("Divisions._id", 1),
Update.Set("Divisions.$", BsonDocumentWrapper.Create<IDivision>(division))
);
The key things going on here are:
- The use of the "$" in Update.Set
- Since Update.Set requires a BsonValue as its second argument we have to use a BsonDocumentWrapper to hold the division value (the IDivision type parameter to Create sets the nominalType at serialization to IDivision which results in the "_t" discriminator being written).
精彩评论