问题
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, because 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.
回答1:
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).
来源:https://stackoverflow.com/questions/4378719/updating-an-embedded-document-in-mongodb-with-official-c-sharp-driver