Перейти к основному содержимому

Руководство по Upsert в MongoDB

· 5 мин. чтения

1. Обзор

Upsert — это комбинация вставки и обновления (inSERT + UPdate = upsert). Мы можем использовать upsert с различными методами обновления, т . е. update , findAndModify и replaceOne .

Здесь, в MongoDB , опция upsert является логическим значением. Предположим, что значение равно true и документы соответствуют указанному фильтру запроса. В этом случае примененная операция обновления обновит документы. Если значение равно true и ни один документ не соответствует условию, этот параметр вставляет в коллекцию новый документ. Новый документ будет содержать поля на основе фильтров и примененных операций.

В этом руководстве мы сначала рассмотрим upsert в запросе MongoDB Shell, а затем воспользуемся кодом драйвера Java.

2. Инициализация базы данных

Прежде чем мы перейдем к выполнению операций upsert , сначала нам нужно настроить новую базу данных foreach и образец коллекции, транспортное средство :

db.vehicle.insertMany([
{
"companyName":"Nissan",
"modelName":"GTR",
"launchYear":2016,
"type":"Sports",
"registeredNo":"EPS 5561"
},
{
"companyName":"BMW",
"modelName":"X5",
"launchYear":2020,
"type":"SUV",
"registeredNo":"LLS 6899"
},
{
"companyName":"Honda",
"modelName":"Gold Wing",
"launchYear":2018,
"type":"Bike",
"registeredNo":"LKS 2477"
}]);

В случае успешной вставки приведенная выше команда напечатает JSON, подобный показанному ниже:

{
"acknowledged" : true,
"insertedIds" : [
ObjectId("623c1db39d55d4e137e4781b"),
ObjectId("623c1db39d55d4e137e4781c"),
ObjectId("623c1db39d55d4e137e4781d")
]
}

Мы успешно добавили фиктивные данные в транспортное средство для сбора .

3. Использование метода обновления

В этом разделе мы научимся использовать опцию upsert с методом обновления . Основная цель параметра upsert — обновить существующий документ на основе примененного фильтра или вставить новый документ, если фильтр не соответствует требованиям .

В качестве иллюстрации мы будем использовать оператор $setOnInsert с опцией upsert , чтобы получить дополнительное преимущество при вставке новых полей в документ.

Давайте проверим запрос, в котором условие фильтра соответствует существующему документу коллекции:

db.vehicle.update(
{
"modelName":"X5"
},
{
"$set":{
"companyName":"Hero Honda"
}
},
{
"upsert":true
});

Приведенный выше запрос вернет следующий документ:

{ 
"nMatched" : 1,
"nUpserted" : 0,
"nModified" : 1
}

Здесь мы увидим код драйвера Java, соответствующий приведенному выше запросу оболочки mongo:

UpdateOptions options = new UpdateOptions().upsert(true);
UpdateResult updateResult = collection.updateOne(Filters.eq("modelName", "X5"),
Updates.combine(Updates.set("companyName", "Hero Honda")), options);
System.out.println("updateResult:- " + updateResult);

В приведенном выше запросе поле modelName «X5» уже существует в коллекции, поэтому поле companyName этого документа будет обновлено до «Hero Honda».

Теперь давайте рассмотрим пример опции upsert с использованием оператора $ setOnInsert . Он будет применим только в случае добавления нового документа:

db.vehicle.update(
{
"modelName":"GTPR"
},
{
"$set":{
"companyName":"Hero Honda"
},
"$setOnInsert":{
"launchYear" : 2022,
"type" : "Bike",
"registeredNo" : "EPS 5562"
},
},
{
"upsert":true
});

Приведенный выше запрос вернет следующий документ:

{
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("623b378ed648af670fe50e7f")
}

Код драйвера Java приведенного выше запроса на обновление с параметром $setOnInsert будет таким:

UpdateResult updateSetOnInsertResult = collection.updateOne(Filters.eq("modelName", "GTPR"),
Updates.combine(Updates.set("companyName", "Hero Honda"),
Updates.setOnInsert("launchYear", 2022),
Updates.setOnInsert("type", "Bike"),
Updates.setOnInsert("registeredNo", "EPS 5562")), options);
System.out.println("updateSetOnInsertResult:- " + updateSetOnInsertResult);

Здесь, в приведенном выше запросе, условие фильтра поля modelName «GTPR» не соответствует ни одному документу коллекции, поэтому мы добавим в коллекцию новый документ. Важно отметить, что $setOnInsert добавляет все поля в новый документ.

4. Использование метода findAndModify

Мы также можем использовать опцию upsert , используя метод findAndModify . Для этого метода значение параметра upsert по умолчанию равно false . Если мы установим для параметра upsert значение true , он будет работать точно так же, как и метод обновления.

Давайте рассмотрим вариант использования метода findAndModify с опцией upsert true :

db.vehicle.findAndModify(
{
query:{
"modelName":"X7"
},
update: {
"$set":{
"companyName":"Hero Honda"
}
},
"upsert":true,
"new":true
});

В этом случае приведенный выше запрос вернет только что созданный документ. Давайте проверим код драйвера Java для приведенного выше запроса:

FindOneAndUpdateOptions upsertOptions = new FindOneAndUpdateOptions();
upsertOptions.returnDocument(ReturnDocument.AFTER);
upsertOptions.upsert(true);
Document resultDocument = collection.findOneAndUpdate(Filters.eq("modelName", "X7"),
Updates.set("companyName", "Hero Honda"), upsertOptions);
System.out.println("resultDocument:- " + resultDocument);

Здесь мы сначала создали условие фильтра и на его основе либо обновим существующий документ, либо добавим новый документ в средство сбора .

5. Использование метода replaceOne

Давайте выполним операцию upsert , используя метод replaceOne . Метод replaceOne MongoDB просто заменяет один документ в коллекции, если условие соответствует.

Во-первых, давайте рассмотрим запрос оболочки Mongo для метода replace:

db.vehicle.replaceOne(
{
"modelName":"GTPR"
},
{
"modelName" : "GTPR",
"companyName" : "Hero Honda",
"launchYear" : 2022,
"type" : "Bike",
"registeredNo" : "EPS 5562"
},
{
"upsert":true
});

Приведенный выше запрос вернет следующий ответ:

{ 
"acknowledged" : true,
"matchedCount" : 1,
"modifiedCount" : 1
}

Теперь давайте напишем приведенный выше запрос, используя код драйвера Java:

Document replaceDocument = new Document();
replaceDocument.append("modelName", "GTPP")
.append("companyName", "Hero Honda")
.append("launchYear", 2022)
.append("type", "Bike")
.append("registeredNo", "EPS 5562");
UpdateResult updateReplaceResult = collection.replaceOne(Filters.eq("modelName", "GTPP"), replaceDocument, options);
System.out.println("updateReplaceResult:- " + updateReplaceResult);

Здесь, в этом случае, нам нужно сначала создать новый документ, которым мы хотим заменить существующий документ, а с опцией upsert true мы заменим документ, только если условие будет выполнено.

6. Заключение

В этой статье мы увидели, как выполнить операцию upsert с различными методами обновления MongoDB. Во-первых, мы научились выполнять upsert с помощью метода update и findAndModify , а затем использовать метод replaceOne . Короче говоря, мы реализовали операцию upsert, используя запрос оболочки Mongo и код драйвера Java.

Реализацию всех кейсов можно найти на GitHub .