Question

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.

Was it helpful?

Solution

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:

  1. The use of the "$" in Update.Set
  2. 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).
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top