sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB Upsert explicado

Muchas operaciones de actualización en MongoDB tienen el potencial de ser upserts. Un upsert es una combinación de una inserción y una actualización.

Funciona así:realiza una operación de actualización basada en criterios de filtro y, si hay coincidencias, solo se actualizan los documentos coincidentes, pero si no hay coincidencias, se inserta un nuevo documento.

Ejemplo

Supongamos que tenemos una colección llamada pets que contiene los siguientes documentos:

 { "_id" : 1, "name" : "Wag", "type" : "Dog" }
 { "_id" : 2, "name" : "Bark", "type" : "Dog" }
 { "_id" : 3, "name" : "Meow", "type" : "Cat" } 

Podríamos realizar la siguiente operación de actualización que establece el upsert parámetro a true :

db.pets.updateOne( 
    { name: "Wag" },
    { $set: { type: "Cow" } },
    { upsert: true }
    )

Resultado:

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

En este caso, había un documento coincidente (es decir, hay un documento con name: "Wag" ) y, por lo tanto, se actualizó el documento correspondiente. No se insertó nada.

Podemos verificar esto de la siguiente manera:

db.pets.find()

Resultado:

 { "_id" : 1, "name" : "Wag", "type" : "Cow" }
 { "_id" : 2, "name" : "Bark", "type" : "Dog" }
 { "_id" : 3, "name" : "Meow", "type" : "Cat" } 

El primer documento ahora tiene un type de Cow .

Ejecutemos otra operación de actualización, nuevamente usando upsert: true . Pero esta vez, no habrá ningún documento coincidente para actualizar.

db.pets.updateOne( 
    { name: "Bubbles" },
    { $set: { type: "Fish" } },
    { upsert: true }
    )

Resultado:

 {
 "acknowledged" : true,
 "matchedCount" : 0,
 "modifiedCount" : 0,
 "upsertedId" : ObjectId("5fe1b4c8d9914101694100b7")
 } 

En este ejemplo, tratamos de encontrar un documento que tenga name: "Bubbles" pero no se encuentra ninguno.

Esta vez podemos ver que el matchedCount es 0 y el modifiedCount es también 0 . Esto significa que ninguno de los documentos existentes se actualizó.

También podemos ver que un upsertedId fue devuelto, lo que significa que se alteró un documento.

Echemos otro vistazo a la colección de documentos:

db.pets.find()

Resultado:

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

Podemos ver que se insertó/alteró un nuevo documento y tiene el mismo ID que se indicó anteriormente.

El upsert ocurrió porque esta vez no había documentos coincidentes para actualizar (y, por lo tanto, se insertó/upsert uno nuevo en su lugar).

Si no hubiéramos configurado upsert: true , ese documento no se habría insertado.

Upsert en actualizaciones masivas

Al realizar una actualización masiva, si desea especificar upsert: true , debe usarlo con Bulk.find.upsert() .

Esto se puede usar con las siguientes operaciones de escritura:

  • Bulk.find.replaceOne()
  • Bulk.find.updateOne()
  • Bulk.find.update()

La sintaxis es así:

Bulk.find(<query>).upsert().update(<update>);
Bulk.find(<query>).upsert().updateOne(<update>);
Bulk.find(<query>).upsert().replaceOne(<replacement>);

Ejemplo:

var bulk = db.pets.initializeUnorderedBulkOp();
bulk.find( { name: "Bruce" } ).upsert().replaceOne(
   {
     name: "Bruce",
     type: "Bat",
   }
);
bulk.execute();

Resultado:

 BulkWriteResult({
 "writeErrors" : [ ],
 "writeConcernErrors" : [ ],
 "nInserted" : 0,
 "nUpserted" : 1,
 "nMatched" : 0,
 "nModified" : 0,
 "nRemoved" : 0,
 "upserted" : [
 {
 "index" : 0,
 "_id" : ObjectId("5fe1c179d9914101694100dd")
 }
 ]
 }) 

Podemos ver que un documento fue alterado. También podemos ver el _id que se generó para ese documento.

Ahora, cuando vemos los documentos de nuestra colección, podemos ver el nuevo documento que se alteró:

db.pets.find()

Resultado:

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