MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB Upsert expliqué

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" }