Как обновить, но не заменить документ с помощью updateOne () MongoDB-драйвера для. NET - PullRequest
3 голосов
/ 13 июля 2020

Ситуация:

У меня есть существующая коллекция документов в MongoDB, в которой я хочу обновить поля указанного c документа с полями входящего документа . Входящий документ имеет тот же класс, что и документы в коллекции, но не все его поля установлены, то есть некоторые поля являются пустыми. Теперь я не хочу заменять весь документ в коллекции, равно как и не хочу заменять все поля, но я хочу заменить только те поля, которые не равны нулю, а остальные оставить как есть .

Этот ответ SO описывает, как заменить весь документ. Я получил это, работая с этим кодом:

public void Update(string id, MyDoc docIn) => _docs.ReplaceOne(doc =>  scan.Id.Equals(ObjectId.Parse(id)), docIn);

Чтобы обновить отдельные поля в документе, в документах предлагается создать «Документ с выражениями оператора обновления» .

Мой вопрос:

Означает ли это, что я должен написать свою собственную функцию, превращающую мой входящий документ в такой «Документ выражений оператора обновления», или есть более удобный способ?

1 Ответ

3 голосов
/ 14 июля 2020

Как вы уже сказали, использование оператора обновления - это путь к go. Идея состоит в том, чтобы использовать фильтр и использовать Отражение объекта, который проходит через свойства.

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

using System.Reflection;

public void Update(string id, MyDoc docIn) 
   => _docs.UpdateOne(doc =>  doc.Id.Equals(ObjectId.Parse(id)), UpdateDocument(docIn);

public UpdateDefinition<myDoc> UpdateDocument(myDoc docIn) 
{
    var builder = Builders<MyDoc>.Update.Set(u => u.Id, docIn.Id);
    foreach(PropertyInfo prop in docIn.GetType().GetProperties())
    {
         var value = docIn.GetType().GetProperty(prop.Name).GetValue(docIn,null);
         if ((prop.Name != "Id") & (value != null))
         {
              builder = builder.Set(prop.Name, value);
         }
    }
    return builder;
}
...