$ (update)
Definição
$
O operador posicional
$
identifica um elemento em uma array para atualizar sem especificar explicitamente a posição do elemento na array.Observação
Desambiguação
Para projetar ou retornar um elemento de array de uma operação de leitura, consulte o operador de projeção
$
.Para atualizar todos os elementos em uma array, consulte o operador posicional
$[]
.Para atualizar todos os elementos que correspondem a uma condição ou condições de filtro de array, consulte o operador posicional filtrado em vez de
$[<identifier>]
.
Compatibilidade
Você pode utilizar o operador posicional $
para sistemas hospedados nos seguintes ambientes:
MongoDB Atlas: o serviço totalmente gerenciado para implantações do MongoDB na nuvem
MongoDB Enterprise: a versão autogerenciada e baseada em assinatura do MongoDB
MongoDB Community: uma versão com código disponível, de uso gratuito e autogerenciada do MongoDB
Sintaxe
O operador posicional $
tem o formato:
{ "<array>.$" : value }
Quando usado com operações de atualização, por exemplo, db.collection.updateOne()
e db.collection.findAndModify()
,
O operador posicional
$
atua como um placeholder para o primeiro elemento que corresponde aquery document
, eo campo
array
deve aparecer como parte doquery document
.
Por exemplo:
db.collection.updateOne( { <array>: value ... }, { <update operator>: { "<array>.$" : value } } )
Comportamento
A partir do MongoDB 5.0, os operadores de atualização processam campos de documento com nomes baseados em cadeia de caracteres em ordem lexicográfica. Os campos com nomes numéricos são processados em ordem numérica. Consulte Atualizar Comportamento de Operadores para detalhes.
upsert
Não use o operador posicional $
com operações upsert porque as inserções usarão $
como um nome de campo no documento inserido.
Arrays agrupadas
O operador posicional $
não pode ser usado para queries que atravessam mais de uma array, como queries que atravessam arrays agrupadas em outras arrays, porque a substituição do espaço reservado $
é um único valor
Desconfigura
Quando usado com o operador $unset
, o operador posicional $
não remove o elemento correspondente da array, mas o define como null
.
Negações
Se a query corresponder à array utilizando um operador de negação, como $ne
, $not
ou $nin
, então você não poderá utilizar o operador posicional para atualizar valores desta array.
No entanto, se a parte negada da query estiver dentro de uma expressão $elemMatch
, então você pode utilizar o operador posicional para atualizar este campo.
Várias correspondências de array
O operador de atualização posicional $
se comporta de forma ambígua ao filtrar vários campos de array.
Quando o servidor executa um método de atualização, ele primeiro executa uma query para determinar quais documentos você deseja atualizar. Se a atualização filtrar documentos em vários campos de array, a chamada subsequente para o operador de atualização posicional $
nem sempre atualizará a posição necessária no array.
Para obter mais informações, consulte o exemplo.
Exemplos
Atualizar valores em uma array
Crie uma collection students
com os seguintes documentos:
db.students.insertMany( [ { "_id" : 1, "grades" : [ 85, 80, 80 ] }, { "_id" : 2, "grades" : [ 88, 90, 92 ] }, { "_id" : 3, "grades" : [ 85, 100, 90 ] } ] )
Para atualizar o primeiro elemento cujo valor é 80
a 82
na array grades
, utilize o operador posicional $
se você não souber a posição do elemento na array:
Importante
Você deve incluir o campo de array como parte do documento query
.
db.students.updateOne( { _id: 1, grades: 80 }, { $set: { "grades.$" : 82 } } )
O operador posicional $
atua como um espaço reservado para a primeira correspondência da atualização do documento de consulta.
Após a operação, a coleção students
contém os seguintes documentos:
{ "_id" : 1, "grades" : [ 85, 82, 80 ] } { "_id" : 2, "grades" : [ 88, 90, 92 ] } { "_id" : 3, "grades" : [ 85, 100, 90 ] }
Atualizar documentos em uma array
O operador posicional $
facilita as atualizações de arrays que contêm documentos incorporados. Use o operador posicional $
para acessar os campos nos documentos incorporados com a notação de ponto no operador $
.
db.collection.updateOne( { <query selector> }, { <update operator>: { "array.$.field" : value } } )
Considere o seguinte documento na collection students
cujo valor do elemento grades
é uma array de documentos incorporados:
{ _id: 4, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 85, mean: 85, std: 8 } ] }
Use o operador posicional $
para atualizar o campo std
do primeiro elemento de array que corresponda à condição grade
igual a 85
:
Importante
Você deve incluir o campo de array como parte do documento query
.
db.students.updateOne( { _id: 4, "grades.grade": 85 }, { $set: { "grades.$.std" : 6 } } )
Após a operação, o documento tem os seguintes valores atualizados:
{ "_id" : 4, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 }, { "grade" : 85, "mean" : 90, "std" : 6 }, { "grade" : 85, "mean" : 85, "std" : 8 } ] }
Atualizar documentos incorporados usando correspondências de vários campos
O operador $
pode atualizar o primeiro elemento de array que corresponda a vários critérios de query com o operador $elemMatch
.
Considere o seguinte documento na collection students
cujo valor de campo grades
é uma array de documentos incorporados:
{ _id: 5, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 90, mean: 85, std: 3 } ] }
No exemplo abaixo, o operador $
atualiza o valor do campo std
no primeiro documento incorporado que tem um campo grade
com um valor menor ou igual a 90
e um campo mean
com um valor maior que 80
:
db.students.updateOne( { _id: 5, grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } } }, { $set: { "grades.$.std" : 6 } } )
Esta operação atualiza o primeiro documento incorporado que corresponde aos critérios, ou seja, o segundo documento incorporado na array:
{ _id: 5, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 6 }, { grade: 90, mean: 85, std: 3 } ] }
Atualizar com várias correspondências de array
O operador de atualização posicional $
se comporta de forma ambígua quando a query tem vários campos de array para filtrar documentos na coleção.
Considere um documento da collection students_deans_list
, que contém arrays de informações dos alunos:
db.students_deans_list.insertMany( [ { _id: 8, activity_ids: [ 1, 2 ], grades: [ 90, 95 ], deans_list: [ 2021, 2020 ] } ] )
No exemplo a seguir, o usuário tenta modificar o campo deans_list
, filtrando documentos usando os campos activity_ids
, deans_list
e grades
, e atualizando o valor de 2021 no campo deans_list
para 2022:
db.students_deans_list.updateOne( { activity_ids: 1, grades: 95, deans_list: 2021 }, { $set: { "deans_list.$": 2022 } } )
Quando o servidor executa o método updateOne
acima, ele filtra os documentos disponíveis utilizando valores nos campos de array fornecidos. Embora o campo deans_list
seja usado no filtro, ele não é o campo usado pelo operador de atualização posicional $
para determinar qual posição na array atualizar:
db.students_deans_list.find( { _id: 8 } )
Saída de exemplo:
{ _id: 8, activity_ids: [ 1, 2 ], grades: [ 90, 95 ], deans_list: [ 2021, 2022 ] }
O método updateOne
correspondeu ao campo deans_list
em 2021, mas o operador de atualização posicional $
alterou o valor 2020 para 2022.