update - MongoDB-Actualizar objetos en una matriz de documento(actualización anidada)
update array mongodb (2)
No hay forma de hacer esto en una sola consulta. Tienes que buscar el documento en la primera consulta:
Si el documento existe:
db.bar.update( {user_id : 123456 , "items.item_name" : "my_item_two" } ,
{$inc : {"items.$.price" : 1} } ,
false ,
true);
Más
db.bar.update( {user_id : 123456 } ,
{$addToSet : {"items" : {''item_name'' : "my_item_two" , ''price'' : 1 }} } ,
false ,
true);
No es necesario agregar la condición {$ne : "my_item_two" }
.
También en el entorno multiproceso debe tener cuidado de que solo un hilo pueda ejecutar el segundo (insertar el caso, si el documento no se encontró) a la vez, de lo contrario se insertarán documentos duplicados.
Supongamos que tenemos la siguiente colección, sobre la cual 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 - Deseo aumentar el precio de "item_name": "my_item_two" y si no existe , debe agregarse al array "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 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 OBJETIVO 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. También solo actualiza el objeto anidado. No hay forma con este comando de actualizar el campo "total" también.
Para la pregunta n. ° 1, divídalo en dos partes. Primero, incremente cualquier documento que tenga "items.item_name" igual a "my_item_two". Para esto, deberá usar el operador posicional "$". Algo como:
db.bar.update( {user_id : 123456 , "items.item_name" : "my_item_two" } ,
{$inc : {"items.$.price" : 1} } ,
false ,
true);
Tenga en cuenta que esto solo incrementará el primer subdocumento coincidente en cualquier matriz (por lo que 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 quieras.
La segunda parte es más difícil. Podemos insertar un nuevo elemento en una matriz sin un "my_item_two" de la siguiente manera:
db.bar.update( {user_id : 123456, "items.item_name" : {$ne : "my_item_two" }} ,
{$addToSet : {"items" : {''item_name'' : "my_item_two" , ''price'' : 1 }} } ,
false ,
true);
Para su pregunta n. ° 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 múltiples campos al mismo tiempo. Algo como:
db.bar.update( {"items.item_name" : {$ne : "my_item_three" }} ,
{$inc : {total : 1 , "items.$.price" : 1}} ,
false ,
true);