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:
-
Verifica che l'elemento dell'array corrisponda alle condizioni in
$elemMatch
è presente e quindi$set
il valore abbinato. -
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. -
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.