Suponha que temos a seguinte coleção, sobre a qual tenho poucas perguntas:
{
"_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 - Quero aumentar o preço de "item_name": "my_item_two" e, se não existir , deve ser anexado à matriz "items".
2 - Como posso atualizar dois campos ao mesmo tempo. Por exemplo, aumente o preço de "my_item_three" e, ao mesmo tempo, aumente o "total" (com o mesmo valor).
Prefiro fazer isso no lado do MongoDB, caso contrário, tenho que carregar o documento no lado do cliente (Python) e construir o documento atualizado e substituí-lo pelo existente no MongoDB.
ATUALIZAÇÃO Isto é o que eu tentei e funciona bem se o objeto existe :
db.test_invoice.update({user_id : 123456 , "items.item_name":"my_item_one"} , {$inc: {"items.$.price": 10}})
Mas se a chave não existe, não faz nada. Também atualiza apenas o objeto aninhado. Não há como este comando atualizar o campo "total" também.
Respostas:
Para a pergunta 1, vamos dividir em duas partes. Primeiro, incremente qualquer documento que tenha "items.item_name" igual a "my_item_two". Para isso, você precisará usar o operador posicional "$". Algo como:
Observe que isso apenas incrementará o primeiro subdocumento correspondente em qualquer matriz (portanto, se você tiver outro documento na matriz com "item_name" igual a "my_item_two", ele não será incrementado). Mas isso pode ser o que você deseja.
A segunda parte é mais complicada. Podemos enviar um novo item para uma matriz sem um "my_item_two" da seguinte maneira:
Para sua pergunta nº 2, a resposta é mais fácil. Para incrementar o total e o preço do item_three em qualquer documento que contenha "my_item_three", você pode usar o operador $ inc em vários campos ao mesmo tempo. Algo como:
fonte
Não há como fazer isso em uma única consulta. Você precisa pesquisar o documento na primeira consulta:
Se o documento existir:
Outro
Não há necessidade de adicionar condição
{$ne : "my_item_two" }
.Também no ambiente multithread, você deve tomar cuidado para que apenas um thread possa executar o segundo (inserir caixa, se o documento não for encontrado) por vez, caso contrário, serão inseridos documentos incorporados duplicados.
fonte
Podemos usar o
$set
operador para atualizar a matriz aninhada dentro do objeto arquivado, atualizar o valorfonte