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

Atualizar Array onde existe ou Inserir novo Item de Array


Você deseja .bulkWrite() por esta. Esta não é realmente uma única operação, portanto, você deseja enviar várias operações em uma única solicitação. Basicamente, tente escrever a atualização com $set onde existem dados ou $push os novos dados onde não existem:
db.collection.bulkWrite([
  { "updateOne": {
    "filter": { "_id": "1", "option.weight": "10" },
    "update": { 
      "$set": { "option.$.price": "30" }
    }
  }},
  { "updateOne": {
    "filter": { "_id": "1", "option.weight": { "$ne": "10" } },
    "update": {
      "$push": { "option": { "weight": "10", "price": "30" } }
    }
  }}
])

O caso positivo é simplesmente o valor e o $ne "nega" a correspondência de igualdade, o que significa que o item não existe. É claro que o $ posicional operador é usado com $set onde isso acontece

Dados os dados, apenas uma das operações realmente corresponderá e será aplicada como uma atualização, apesar de duas operações serem enviadas no "lote".

Se você também quiser "upserts" para todo o documento, precisará adicionar outra operação ao final disso. Observe que você não pode aplicar "upsert" como uma opção em nenhuma das outras declarações, especialmente a $ne porque isso criaria um novo documento onde o item da matriz não existe, não apenas o _id :
db.collection.bulkWrite([
  { "updateOne": {
    "filter": { "_id": "1", "option.weight": "10" },
    "update": { 
      "$set": { "option.$.price": "30" }
    }
  }},
  { "updateOne": {
    "filter": { "_id": "1", "option.weight": { "$ne": "10" } },
    "update": {
      "$push": { "option": { "weight": "10", "price": "30" } }
    }
  }},
  { "updateOne": {
    "filter": { "_id": 1 },
    "update": {
      "$setOnInsert": {
        "option": [
           { "weight": "10", "price": "30" }
         ]
      }
    },
    "upsert": true
  }}
])

O $setOnInsert é a ajuda principal aqui, além dessa última operação ser a única marcada como "upsert" . Essa combinação garante que, onde o "documento" primário for encontrado, nada realmente aconteça, mas quando não for encontrado, o novo item de matriz será adicionado.

Como nota lateral, sugiro fortemente armazenar valores numéricos na verdade como numéricos em vez de strings. Não apenas economiza espaço na maioria dos casos, mas também é muito mais útil dessa maneira.