Supongamos que tenemos la siguiente colección, sobre la que tengo algunas preguntas:
{
"_id" : ObjectId("4faaba123412d654fe83hg876"),
"user_id" : 123456,
"total" : 100,
"items" : [
{
"item_name" : "my_item_one",
"price" : 20
},
{
"item_name" : "my_item_two",
"price" : 50
},
{
"item_name" : "my_item_three",
"price" : 30
}
]
}
1 - Quiero aumentar el precio de "item_name": "my_item_two" y, si no existe , debería adjuntarse a la matriz "items".
2 - ¿Cómo puedo actualizar dos campos al mismo tiempo? Por ejemplo, aumente el precio de "my_item_three" y al mismo tiempo aumente el "total" (con el mismo valor).
Prefiero hacer esto en el lado de MongoDB, de lo contrario tengo que cargar el documento en el lado del cliente (Python) y construir el documento actualizado y reemplazarlo con el existente en MongoDB.
ACTUALIZAR Esto es lo que he intentado y funciona bien SI EL Objeto existe :
db.test_invoice.update({user_id : 123456 , "items.item_name":"my_item_one"} , {$inc: {"items.$.price": 10}})
Pero si la clave no existe, no hace nada. Además, solo actualiza el objeto anidado. Con este comando no hay manera de actualizar el campo "total" también.
Respuestas:
Para la pregunta # 1, dividámoslo en dos partes. Primero, incremente cualquier documento que tenga "items.item_name" igual a "my_item_two". Para ello, deberá utilizar el operador posicional "$". Algo como:
Tenga en cuenta que esto solo incrementará el primer subdocumento coincidente en cualquier matriz (por lo tanto, si tiene otro documento en la matriz con "item_name" igual a "my_item_two", no se incrementará). Pero esto podría ser lo que quieres.
La segunda parte es más complicada. Podemos insertar un nuevo elemento en una matriz sin un "my_item_two" de la siguiente manera:
Para su pregunta # 2, la respuesta es más fácil. Para incrementar el total y el precio de item_three en cualquier documento que contenga "my_item_three", puede usar el operador $ inc en varios campos al mismo tiempo. Algo como:
fuente
No hay forma de hacer esto en una sola consulta. Tienes que buscar el documento en la primera consulta:
Si el documento existe:
Más
No es necesario agregar condición
{$ne : "my_item_two" }
.También en entornos multiproceso, debe tener cuidado de que solo un hilo pueda ejecutar el segundo (insertar caso, si no se encontró el documento) a la vez, de lo contrario se insertarán documentos incrustados duplicados.
fuente
Podemos usar el
$set
operador para actualizar la matriz anidada dentro del objeto archivado, actualizar el valorfuente