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

Inserisci array dove l'elemento non esiste altrimenti aggiornalo (con più condizioni)

Simile alla la tua domanda precedente , utilizzi .bulkWrite() ma poiché la selezione dell'elemento dell'array ha "condizioni multiple", è qui che usi $elemMatch :

db.collection.bulkWrite([
  { "updateOne": {
    "filter": { 
      "_id": "1", 
      "option": { 
        "$elemMatch": { "weight": "40", "size": "40" }
      }
    },
    "update": { 
      "$set": { "option.$.price": "300" }
    }
  }},
  { "updateOne": {
    "filter": {
      "_id": "1",
      "option": {
        "$not": {
          "$elemMatch": { "weight": "40", "size": "40" }
        }
      }
    },
    "update": {
      "$push": { "option": { "weight": "40", "size": "40",  "price": "300" } }
    }
  }},
  { "updateOne": {
    "filter": { "_id": 1 },
    "update": {
      "$setOnInsert": {
        "option": [
           { "weight": "40", "size": "40",  "price": "300" }
         ]
      }
    },
    "upsert": true
  }}
])

Quindi le operazioni sono:

  1. Verifica che l'elemento dell'array corrisponda alle condizioni in $elemMatch è presente e quindi $set il valore abbinato.

  2. Verifica che l'elemento dell'array sia $not presente in negazione. In alternativa puoi utilizzare $ne su ogni proprietà, ma negare la condizione in cui entrambe corrispondono è un po' più pulito.

     "$elemMatch": { "weight": { "$ne": "40" }, "size": { "$ne": "40" } }
    

    In ogni caso $push il nuovo elemento dell'array quando uno non viene trovata la corrispondenza con i criteri forniti.

  3. Tenta un "upsert" solo dove il documento principale _id non viene trovato e utilizzare $setOnInsert in modo che se il documento viene trovato questa operazione non ha effetto.

Come prima, solo uno di questi scriverà effettivamente qualcosa nonostante l'intero batch venga inviato al server.