Обновление встроенного документа в MongoDB с помощью официального драйвера C # - PullRequest
5 голосов
/ 07 декабря 2010

Если у меня есть коллекция Компании, которая содержит встроенные подразделения:

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

Каков наилучший способ сохранить / обновить весь отдел при использовании официального драйвера 10gen C # ? (Последний выпуск 0.9.)

Я использую Update.AddToSetWrapped для добавления подразделений, и это прекрасно работает, но я также хотел бы иметь возможность обновлять документы в зависимости от их _id.

Например, если я определю следующий метод обновления:

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

и назовите это так:

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

Затем в набор будет добавлен новый экземпляр Division, поскольку, хотя «_id» по-прежнему равно 1, имя отличается, и поэтому это уникальный документ.

Так, что есть хороший способ обновить весь встроенный документ?

Пока я не придумаю лучшее решение, я собираюсь сначала $pull исходное Подразделение, а затем $addToSet с измененным Подразделением. Это работает, но, очевидно, не идеально, поскольку оно выполняет два отдельных обновления.

1 Ответ

11 голосов
/ 07 декабря 2010

Вы можете использовать функцию изменения позиционного массива в MongoDB для одновременного обновления всего деления в массиве следующим образом:

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

Здесь происходят следующие ключевые вещи:

  1. Использование «$» в Update.Set
  2. Поскольку Update.Set требует BsonValue в качестве второго аргумента, мы должны использовать BsonDocumentWrapper для хранения значения деления (параметр типа IDivision для Create устанавливаетnominalType при сериализации в IDivision, что приводит к записи "_t" дискриминатора).
...