MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Spiegazione dell'upsert di MongoDB

Molte operazioni di aggiornamento in MongoDB hanno il potenziale per essere upsert. Un upsert è una combinazione di un inserto e un aggiornamento.

Funziona così:esegui un'operazione di aggiornamento in base a criteri di filtro e, se ci sono corrispondenze, vengono aggiornati solo i documenti corrispondenti, ma se non ci sono corrispondenze, viene inserito un nuovo documento.

Esempio

Supponiamo di avere una collezione chiamata pets che contiene i seguenti documenti:

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

Potremmo eseguire la seguente operazione di aggiornamento che imposta il upsert parametro su true :

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

Risultato:

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

In questo caso, c'era un documento corrispondente (ovvero c'è un documento con name: "Wag" ) e pertanto il documento di corrispondenza è stato aggiornato. Non è stato inserito nulla.

Possiamo verificarlo come segue:

db.pets.find()

Risultato:

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

Il primo documento ora ha un type di Cow .

Eseguiamo un'altra operazione di aggiornamento, sempre utilizzando upsert: true . Ma questa volta, non ci sarà alcun documento corrispondente da aggiornare.

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

Risultato:

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

In questo esempio, proviamo a trovare un documento che abbia name: "Bubbles" ma non si trova nessuno.

Questa volta possiamo vedere che il matchedCount è 0 e il modifiedCount è anche 0 . Ciò significa che nessuno dei documenti esistenti è stato aggiornato.

Possiamo anche vedere che un upsertedId è stato restituito, il che significa che un documento è stato capovolto.

Diamo un'altra occhiata alla raccolta di documenti:

db.pets.find()

Risultato:

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

Possiamo vedere che un nuovo documento è stato inserito/smontato e ha lo stesso ID come indicato sopra.

L'upsert si è verificato perché questa volta non c'erano documenti corrispondenti da aggiornare (e quindi ne è stato inserito/upsert uno nuovo).

Se non avessimo impostato upsert: true , quel documento non sarebbe stato inserito.

Aggiornamenti in blocco

Quando si esegue un aggiornamento in blocco, se si desidera specificare upsert: true , devi usarlo con Bulk.find.upsert() .

Può essere utilizzato con le seguenti operazioni di scrittura:

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

La sintassi è questa:

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

Esempio:

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

Risultato:

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

Possiamo vedere che un documento è stato alterato. Possiamo anche vedere il _id che è stato generato per quel documento.

Ora, quando visualizziamo i documenti nella nostra raccolta, possiamo vedere il nuovo documento che è stato aggiornato:

db.pets.find()

Risultato:

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