MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Explicação do Upsert do MongoDB


Muitas operações de atualização no MongoDB têm o potencial de serem upserts. Um upsert é uma combinação de uma inserção e uma atualização.

Funciona assim:Você executa uma operação de atualização com base em critérios de filtro, e se houver correspondências, apenas os documentos correspondentes serão atualizados, mas se não houver correspondências, um novo documento será inserido.

Exemplo


Suponha que tenhamos uma coleção chamada pets que contém os seguintes documentos:
 { "_id" : 1, "name" : "Wag", "type" : "Dog" }
 { "_id" : 2, "name" : "Bark", "type" : "Dog" }
 { "_id" : 3, "name" : "Meow", "type" : "Cat" } 

Poderíamos realizar a seguinte operação de atualização que define o upsert parâmetro para true :
db.pets.updateOne( 
    { name: "Wag" },
    { $set: { type: "Cow" } },
    { upsert: true }
    )

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

Nesse caso, havia um documento correspondente (ou seja, há um documento com name: "Wag" ) e, portanto, o documento correspondente foi atualizado. Nada foi inserido.

Podemos verificar isso da seguinte forma:
db.pets.find()

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

O primeiro documento agora tem um type de Cow .

Vamos executar outra operação de atualização, novamente usando upsert: true . Mas desta vez, não haverá nenhum documento correspondente para atualizar.
db.pets.updateOne( 
    { name: "Bubbles" },
    { $set: { type: "Fish" } },
    { upsert: true }
    )

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

Neste exemplo, tentamos encontrar um documento que tenha name: "Bubbles" mas não há nenhum para ser encontrado.

Desta vez, podemos ver que o matchedCount é 0 , e o modifiedCount também é 0 . Isso significa que nenhum dos documentos existentes foi atualizado.

Também podemos ver que um upsertedId foi retornado, o que significa que um documento foi upserted.

Vamos dar outra olhada na coleção 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 um novo documento foi inserido/inserido e possui o mesmo ID indicado acima.

O upsert ocorreu porque desta vez não havia documentos correspondentes para atualizar (e, portanto, um novo foi inserido/upserted).

Se não tivéssemos definido upsert: true , esse documento não teria sido inserido.

Upsert em atualizações em massa


Ao realizar uma atualização em massa, se você deseja especificar upsert: true , você precisa usá-lo com Bulk.find.upsert() .

Isso pode ser usado com as seguintes operações de gravação:
  • Bulk.find.replaceOne()
  • Bulk.find.updateOne()
  • Bulk.find.update()

A sintaxe fica assim:
Bulk.find(<query>).upsert().update(<update>);
Bulk.find(<query>).upsert().updateOne(<update>);
Bulk.find(<query>).upsert().replaceOne(<replacement>);

Exemplo:
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 um documento foi upserted. Também podemos ver o _id que foi gerado para esse documento.

Agora, quando visualizamos os documentos em nossa coleção, podemos ver o novo documento que foi atualizado:
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" }