Definición
$El operador posicional
$identifica un elemento en un arreglo para actualizar sin especificar explícitamente la posición del elemento en el arreglo.Nota
Desambiguación
Para proyectar o devolver un elemento de matriz desde una operación de lectura, consulte la
$operador de proyección en su lugar.Para actualizar todos los elementos en un arreglo, se puede consultar en cambio el operador posicional all
$[].Para actualizar todos los elementos que coincidan con una condición o condiciones de filtro de arreglo, se puede consultar en cambio el operador posicional filtrado
$[<identifier>].
Compatibilidad
Se puede usar el operador posicional $ para implementaciones alojadas en los siguientes entornos:
MongoDB Atlas: El servicio totalmente gestionado para implementaciones de MongoDB en la nube
MongoDB Enterprise: La versión basada en suscripción y autogestionada de MongoDB
MongoDB Community: La versión de MongoDB con código fuente disponible, de uso gratuito y autogestionada.
Sintaxis
El operador posicional $ tiene la forma:
{ "<array>.$" : value }
Cuando se utiliza con operaciones de actualización, por ejemplo db.collection.updateOne() y db.collection.findAndModify(),
el operador posicional
$actúa como marcador de posición del primer elemento que coincida conquery document, yel campo
arraydebe aparecer como parte dequery document.
Por ejemplo:
db.collection.updateOne( { <array>: value ... }, { <update operator>: { "<array>.$" : value } } )
Comportamiento
A partir de MongoDB 5.0, los operadores de actualización procesan los campos de documentos con nombres basados en cadenas en orden lexicográfico. Los campos con nombres numéricos se procesan en orden numérico. Consulta Comportamiento del operador de actualización para obtener más información.
inserción
No se debe utilizar el operador $ en operaciones de actualización o inserción. Si la query de actualización no coincide con ningún documento existente, la inserción falla porque el operador $ necesita un elemento de arreglo coincidente.
Arreglos anidados
El operador posicional $ no puede utilizarse para aquellas query que atraviesan más de un arreglo, como las query que atraviesan arreglos anidados dentro de otros arreglos, debido a que el reemplazo para el marcador de posición $ es un valor único
No establecidos
Cuando se usa con el operador $unset, el operador posicional $ no elimina el elemento coincidente del arreglo, sino que lo establece en null.
Negaciones
Si la query coincide con el arreglo utilizando un operador de negación, como $ne, $not, o $nin, entonces no se puede utilizar el operador posicional para actualizar los valores de este arreglo.
Sin embargo, si la parte negada de la query está dentro de una expresión $elemMatch, entonces se puede utilizar el operador posicional para actualizar este campo.
Coincidencias de arreglos múltiples
El operador de actualización posicional $ se comporta de forma ambigua en el filtrado de varios campos de arreglo.
Cuando el servidor ejecuta un método de actualización, primero ejecuta una query para determinar qué documentos quieres actualizar. Si la actualización filtra documentos en varios campos del arreglo, la llamada posterior al operador de actualización posicional $ no siempre actualiza la posición requerida en el arreglo.
Para obtener más información, consulta el ejemplo.
Ejemplos
Actualizar valores en un arreglo
Cree una colección students con los siguientes documentos:
db.students.insertMany( [ { "_id" : 1, "grades" : [ 85, 80, 80 ] }, { "_id" : 2, "grades" : [ 88, 90, 92 ] }, { "_id" : 3, "grades" : [ 85, 100, 90 ] } ] )
Para actualizar el primer elemento cuyo valor es 80 a 82 en el arreglo grades, utiliza el operador posicional $ si no conoces la posición del elemento en el arreglo:
Importante
Se debe incluir el campo de arreglo como parte del documento query.
db.students.updateOne( { _id: 1, grades: 80 }, { $set: { "grades.$" : 82 } } )
El operador posicional $ actúa como un marcador de posición para la primera coincidencia del documento de query a actualizar.
Después de la operación, la colección students contiene los siguientes documentos:
{ "_id" : 1, "grades" : [ 85, 82, 80 ] } { "_id" : 2, "grades" : [ 88, 90, 92 ] } { "_id" : 3, "grades" : [ 85, 100, 90 ] }
Se pueden actualizar documentos en un arreglo
El operador posicional $ facilita las actualizaciones de arreglos que contienen documentos incrustados. Utiliza el operador posicional $ para acceder a los campos en los documentos incrustados con la notación de puntos en el operador $.
db.collection.updateOne( { <query selector> }, { <update operator>: { "array.$.field" : value } } )
Se puede considerar el siguiente documento en la colección students cuyo valor del elemento grades es un arreglo de documentos incrustados:
{ _id: 4, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 85, mean: 85, std: 8 } ] }
Utiliza el operador posicional $ para actualizar el campo std del primer elemento del arreglo que coincida con la condición grade igual a 85:
Importante
Se debe incluir el campo de arreglo como parte del documento query.
db.students.updateOne( { _id: 4, "grades.grade": 85 }, { $set: { "grades.$.std" : 6 } } )
Después de la operación, el documento tiene los siguientes valores actualizados:
{ "_id" : 4, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 }, { "grade" : 85, "mean" : 90, "std" : 6 }, { "grade" : 85, "mean" : 85, "std" : 8 } ] }
Se pueden actualizar los documentos incrustados mediante múltiples coincidencias de campo
El operador $ puede actualizar el primer elemento del arreglo que coincida con varios criterios de query especificados con el operador $elemMatch.
Se puede considerar el siguiente documento de la colección students cuyo valor de campo grades es un arreglo de documentos incrustados:
{ _id: 5, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 90, mean: 85, std: 3 } ] }
En el siguiente ejemplo, el operador $ actualiza el valor del campo std en el primer documento incrustado que tiene el campo grade con un valor menor o igual a 90 y un campo mean con un valor mayor que 80:
db.students.updateOne( { _id: 5, grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } } }, { $set: { "grades.$.std" : 6 } } )
Esta operación actualiza el primer documento incrustado que cumple con los criterios, es decir, el segundo documento incrustado en el arreglo:
{ _id: 5, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 6 }, { grade: 90, mean: 85, std: 3 } ] }
Se puede actualizar con coincidencias de múltiples arreglos
El operador posicional de actualización $ se comporta de forma ambigua cuando la query tiene varios campos de arreglo para filtrar los documentos de la colección.
Se puede considerar un documento en la colección students_deans_list, que contiene arreglos de información de estudiantes:
db.students_deans_list.insertMany( [ { _id: 8, activity_ids: [ 1, 2 ], grades: [ 90, 95 ], deans_list: [ 2021, 2020 ] } ] )
En el siguiente ejemplo, el usuario intenta modificar el campo deans_list, aplicando un filtro a los documentos utilizando los campos activity_ids, deans_list y grades y para actualizar el valor de 2021 en el campo deans_list a 2022:
db.students_deans_list.updateOne( { activity_ids: 1, grades: 95, deans_list: 2021 }, { $set: { "deans_list.$": 2022 } } )
Cuando el servidor ejecuta el método updateOne mencionado anteriormente, filtra los documentos disponibles usando los valores de los campos del arreglo proporcionados. Aunque el campo deans_list se utiliza en el filtro, no es el campo que utiliza el operador de actualización posicional $ para determinar la posición del arreglo que debe actualizarse:
db.students_deans_list.find( { _id: 8 } )
Ejemplo de salida:
{ _id: 8, activity_ids: [ 1, 2 ], grades: [ 90, 95 ], deans_list: [ 2021, 2022 ] }
El método updateOne coincidió con el campo deans_list en 2021, pero el operador de actualización posicional $ cambió el valor 2020 a 2022.
Para evitar resultados inesperados al hacer coincidir varios arreglos, se debe usar en cambio el operador posicional filtrado $[<identifier>].
Obtén más información
Para ejemplos que utilizan el operador $ para actualizar arreglos, consulta Actualizar elementos de arreglo en un documento con operadores posicionales de MQL.