Semelhante a sua pergunta anterior , você usa
.bulkWrite()
mas como a seleção do elemento da matriz tem "múltiplas condições", é aqui que você usa $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
}}
])
Então as operações são:
-
Teste as condições de correspondência do elemento da matriz em$elemMatch
está presente e, em seguida,$set
o valor correspondido.
-
Teste se o elemento da matriz é$not
presente na negação. Você pode usar alternativamente$ne
em cada propriedade, mas negando a condição em que ambas as correspondências são um pouco mais limpas.
"$elemMatch": { "weight": { "$ne": "40" }, "size": { "$ne": "40" } }
De qualquer forma, você$push
o novo elemento de matriz quando um não correspondente aos critérios fornecidos é encontrado.
-
Tente um "upsert" somente onde o documento principal_id
não foi encontrado e use$setOnInsert
para que, se o documento for encontrado, essa operação não faça nada.
Da mesma forma que antes, apenas um deles realmente escreverá alguma coisa, apesar de todo o lote ser enviado ao servidor.