Подтвердить что ты не робот

Обновление в Mongo DB с использованием официального драйвера С#

В официальной документации mongodb упоминаются upserts, поэтому было бы очень приятно написать команду upsert вместо:

if (_campaignRepo.Exists(camp))
{
    _campaignRepo.DeleteByIdAndSystemId(camp);
}

_campaignRepo.Save(camp);

что-то, что реализовало бы эту логику на уровне db, если это возможно. Итак, каков способ сделать upsert, если он есть?

4b9b3361

Ответ 1

Следующий код из рабочего приложения:

weekplanStore.Update(
    Query.EQ("weekNumber", week),
    Update.Replace(rawWeekPlan),
    UpdateFlags.Upsert);

WeekplanStore - это моя коллекция MongoDB, и код обновит документ, найденный с помощью запроса, в первом аргументе или добавит новый, если он не найден. "Трюк" заключается в использовании модификатора UpdateFlags.Upsert.

rawWeekPlan - это объект, вставленный или обновленный, и имеет следующий тип:

private class RawWeekPlan
{
    public ObjectId id;
    public int weekNumber;
    public WeekPlanEntry[] entries;
}

и автоматически переключится на bson с помощью драйвера.

Ответ 2

Версия 2 драйвера MongoDB С# требует установки флага IsUpsert в командах записи. В этом примере будет показан весь документ.

var newDoc = new BsonDocument { { "_id", 123 }, { "someKey", "someValue" } };
var result = await collection.ReplaceOneAsync(
                filter: new BsonDocument("_id", 123),
                options: new UpdateOptions { IsUpsert = true },
                replacement: newDoc);

Версия 1 драйвера MongoDB С# реализует эту логику в команде Save.

var newDoc = new BsonDocument { { "_id", 123 }, { "someKey", "someValue" } };
collection.Save(newDoc);

Метод Save представляет собой комбинацию вставки и обновления. Если элемент Id документа имеет значение, то предполагается, что он является существующим документом, и Save вызывает Update для документа (устанавливая флаг Upsert на тот случай, если он действительно является новым документом). В противном случае предполагается, что это новый документ, и "Сохранить" вызывает "Вставить" после первого присвоения вновь сгенерированного уникального значения члену Id.

Ссылка: http://mongodb.github.io/mongo-csharp-driver/1.11/driver/#save-tdocument-method

Примечание. Однако для этого требуется правильное отображение поля Id. Больше информации об этом здесь: http://mongodb.github.io/mongo-csharp-driver/1.11/serialization/#identifying-the-id-field-or-property

Ответ 3

Начиная с версии 2.0 драйвера есть новый API с асинхронным интерфейсом. Старый API больше не должен использоваться, поскольку он блокирует фасад над новым API и устарел.

Рекомендуемый в настоящее время способ повышения уровня документа - вызов и ожидание ReplaceOneAsync с включенным флагом IsUpsert и фильтром, соответствующим соответствующему документу:

Hamster hamster = ...
var replaceOneResult = await collection.ReplaceOneAsync(
    doc => doc.Id == hamster.Id, 
    hamster, 
    new UpdateOptions {IsUpsert = true});

Вы можете проверить, была ли операция вставкой или обновлением, просмотрев ReplaceOneResult.MatchedCount:

Ответ 4

Вы можете использовать регулярную команду обновления, но просто передайте ей флаг обновления Upsert

MongoCollection collection = db.GetCollection("matches");
var query = new QueryDocument("recordId", recordId);

var update = Update.Set("FirstName", "John").Set("LastName","Doe");
matchCollection.Update(query, update, UpdateFlags.Upsert, SafeMode.False);

Этот код адаптирован из рабочего приложения (сокращен для ясности)