2010-12-07 30 views
5

Si tengo una colección Empresa Divisiones que contiene incrustado:actualización de un documento incrustado en MongoDB con un funcionario C# conductor

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

¿Cuál es la mejor manera de guardar/actualizar toda una división cuando se utiliza el official 10gen C# driver? (La última versión 0.9.)

Estoy usando Update.AddToSetWrapped para agregar Divisiones, y eso funciona bien, pero también me gustaría poder actualizar documentos según su _id.

Por ejemplo, si defino el siguiente método Update:

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

y lo llaman así:

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

A continuación se añadirá una nueva instancia de la División para el conjunto, ya que aunque el "_id" sigue siendo 1, el nombre es diferente y, por lo tanto, es un documento único.

Entonces, ¿qué hay una buena manera de actualizar todo un documento incrustado?

Hasta que se me ocurra una mejor solución Voy a la primera División $pull y luego a $addToSet con la División modificada. Eso funciona, pero obviamente no es ideal, ya que realiza dos actualizaciones por separado.

Respuesta

11

Se puede utilizar la función de modificación matriz posicional de MongoDB para actualizar una división entera de la matriz a la vez de la siguiente manera:

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

Las cosas claves pasando aquí son:

  1. El uso de "$" en Update.Set
  2. Dado que Update.Set requiere un BsonValue como segundo argumento, debemos usar BsonDocumentWrapper para mantener el valor de división (el parámetro de tipo IDivision en Create establece el tipo nominal en la serialización a IDivision que da como resultado que se escriba el discriminador "_t").
Cuestiones relacionadas