De nombreuses opérations de mise à jour dans MongoDB peuvent être des upserts. Un upsert est une combinaison d'un insert et d'une mise à jour.
Cela fonctionne comme ceci :vous effectuez une opération de mise à jour basée sur des critères de filtre, et s'il y a des correspondances, seuls les documents correspondants sont mis à jour, mais s'il n'y a pas de correspondances, un nouveau document est inséré.
Exemple
Supposons que nous ayons une collection appelée pets
qui contient les documents suivants :
{ "_id" : 1, "name" : "Wag", "type" : "Dog" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Nous pourrions effectuer l'opération de mise à jour suivante qui définit le upsert
paramètre à true
:
db.pets.updateOne(
{ name: "Wag" },
{ $set: { type: "Cow" } },
{ upsert: true }
)
Résultat :
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
Dans ce cas, il y avait un document correspondant (c'est-à-dire qu'il y a un document avec name: "Wag"
) et par conséquent le document correspondant a été mis à jour. Rien n'a été inséré.
Nous pouvons le vérifier comme suit :
db.pets.find()
Résultat :
{ "_id" : 1, "name" : "Wag", "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Le premier document a maintenant un type
de Cow
.
Exécutons une autre opération de mise à jour, en utilisant à nouveau upsert: true
. Mais cette fois, il n'y aura pas de document correspondant à mettre à jour.
db.pets.updateOne(
{ name: "Bubbles" },
{ $set: { type: "Fish" } },
{ upsert: true }
)
Résultat :
{ "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0, "upsertedId" : ObjectId("5fe1b4c8d9914101694100b7") }
Dans cet exemple, nous essayons de trouver un document qui a name: "Bubbles"
mais il n'y en a pas à trouver.
Cette fois, nous pouvons voir que le matchedCount
est 0
, et le modifiedCount
vaut aussi 0
. Cela signifie qu'aucun des documents existants n'a été mis à jour.
Nous pouvons également voir qu'un upsertedId
a été renvoyé, ce qui signifie qu'un document a été mis à jour.
Reprenons la collection de documents :
db.pets.find()
Résultat :
{ "_id" : 1, "name" : "Wag", "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" } { "_id" : ObjectId("5fe1b4c8d9914101694100b7"), "name" : "Bubbles", "type" : "Fish" }
Nous pouvons voir qu'un nouveau document a été inséré/mis à jour et qu'il a le même ID que celui indiqué ci-dessus.
L'upsert s'est produit parce que cette fois il n'y avait pas de documents correspondants à mettre à jour (et donc un nouveau a été inséré/mis à jour à la place).
Si nous n'avions pas défini upsert: true
, ce document n'aurait pas été inséré.
Upsert sur les mises à jour groupées
Lors d'une mise à jour groupée, si vous souhaitez spécifier upsert: true
, vous devez l'utiliser avec Bulk.find.upsert()
.
Cela peut être utilisé avec les opérations d'écriture suivantes :
Bulk.find.replaceOne()
Bulk.find.updateOne()
Bulk.find.update()
La syntaxe ressemble à ceci :
Bulk.find(<query>).upsert().update(<update>);
Bulk.find(<query>).upsert().updateOne(<update>);
Bulk.find(<query>).upsert().replaceOne(<replacement>);
Exemple :
var bulk = db.pets.initializeUnorderedBulkOp();
bulk.find( { name: "Bruce" } ).upsert().replaceOne(
{
name: "Bruce",
type: "Bat",
}
);
bulk.execute();
Résultat :
BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 0, "nUpserted" : 1, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ { "index" : 0, "_id" : ObjectId("5fe1c179d9914101694100dd") } ] })
Nous pouvons voir qu'un document a été modifié. Nous pouvons également voir le _id
qui a été généré pour ce document.
Désormais, lorsque nous visualisons les documents de notre collection, nous pouvons voir le nouveau document qui a été mis à jour :
db.pets.find()
Résultat :
{ "_id" : 1, "name" : "Wag", "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" } { "_id" : ObjectId("5fe1b4c8d9914101694100b7"), "name" : "Bubbles", "type" : "Fish" } { "_id" : ObjectId("5fe1c179d9914101694100dd"), "name" : "Bruce", "type" : "Bat" }