Quiere .bulkWrite()
para esto. En realidad, esta no es una sola operación, por lo que desea enviar varias operaciones en una sola solicitud. Básicamente intenta escribir la actualización con $set
donde existen datos o $push
los nuevos datos donde no existen:
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" } }
}
}}
])
El caso positivo es simplemente el valor, y el $ne
"niega" la coincidencia de igualdad, lo que significa que el elemento no existe. Por supuesto, el posicional $
operador
se usa con $set
donde lo hace
Dados los datos, solo una de las operaciones coincidirá y se aplicará como una actualización a pesar de que se envíen dos operaciones en el "lote".
Si también desea "upserts" para todo el documento, debe agregar otra operación al final de eso. Tenga en cuenta que no puede aplicar "upsert" como una opción en ninguna de las otras declaraciones, especialmente $ne
porque eso crearía un nuevo documento donde el elemento de la matriz no existe, no solo el _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
}}
])
El $setOnInsert
es la ayuda principal aquí aparte de que la última operación es la única marcada como "upsert"
. Esa combinación asegura que donde se encuentra el "documento" principal, en realidad no sucede nada, pero cuando no se encuentra, se agrega el nuevo elemento de matriz.
Como nota al margen, recomendaría encarecidamente almacenar valores numéricos en realidad como numéricos en lugar de cadenas. No solo ahorra espacio en la mayoría de los casos, sino que también es mucho más útil de esa manera.