2010-12-07 17 views
5

Wenn ich eine Firma Sammlung, die eingebettete Divisionen enthält:Aktualisieren ein eingebettetes Dokument in MongoDB mit offiziellem C# Fahrern

{ 
    "_id": 1 
    "_t": "Company", 
    "Name": "Test Company" 
    "Divisions": [ 
    { 
     "_id": 1 
     "_t": "Division", 
     "Name": "Test Division 1" 
    }, 
    { 
     "_id": 2 
     "_t": "Division", 
     "Name": "Test Division 2" 
    } 
    ] 
} 

Was ist der beste Weg, eine ganze Abteilung speichern/aktualisieren, wenn die official 10gen C# driver verwenden? (Die neueste Version 0.9)

Ich benutze Update.AddToSetWrapped, um Divisionen hinzuzufügen, und das funktioniert gut, aber ich würde auch gerne in der Lage sein, Dokumente abhängig von ihrer _id zu aktualisieren.

Zum Beispiel, wenn ich definiere die folgende Update-Methode:

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); 
} 

und es wie so nennen:

var division = GetDivisionById(1); 
division.Name = "New Name"; 
UpdateDivision(division); 

Dann wird eine neue Instanz von Division zu dem Satz hinzugefügt werden, denn obwohl Die "_id" ist immer noch 1, der Name ist anders, und daher ist es ein einzigartiges Dokument.

Also, was gibt es eine gute Möglichkeit, ein ganzes eingebettetes Dokument zu aktualisieren?

Bis ich mit einer besseren Lösung komme ich gehe zuerst $pull der ursprünglichen Division und dann $addToSet mit der modifizierten Division. Das funktioniert, ist aber offensichtlich nicht ideal, da es zwei separate Updates durchführt.

Antwort

11

Sie können die Positions Array Modifikation Merkmal von MongoDB verwenden, um eine ganze Division in dem Array auf einmal zu aktualisieren, wie folgt:

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)) 
); 

Die wichtigsten Dinge hier los sind:

  1. Die Verwendung von "$" in Update.Set
  2. Da Update.Set einen BsonValue als zweites Argument benötigt, müssen wir einen BsonDocumentWrapper verwenden, um den Divisionswert zu halten (der IDivision-Typparameter auf Create setzt den nominalType bei der Serialisierung) zu IDivision, was dazu führt, dass der Diskriminator "_t" geschrieben wird.
Verwandte Themen