Definición
$El posicional
$El operador limita el contenido de un<array>para devolver el primer elemento que coincide con la condición de consulta en la matriz.Utilice en
$el Documento de proyección del métodofind()o del métodofindOne()cuando solo necesita un elemento de matriz en particular en los documentos seleccionados.Consulta el operador de agregación
$filterpara devolver un arreglo con solo aquellos elementos que cumplan con la condición especificada.Nota
Desambiguación
Para especificar un elemento de arreglo que deseas actualizar, consulta el operador $ posicional para actualizaciones.
Consideraciones sobre el uso
Tanto el operador $ como el operador $elemMatch proyectan el primer elemento coincidente de un arreglo basado en una condición.
El operador $ proyecta el primer elemento coincidente del arreglo de cada documento en una colección basado en alguna condición de la instrucción del query.
El operador de proyección $elemMatch acepta un argumento de condición explícito. Esto permite proyectar en función de una condición que no está en la query, o si se necesita proyectar en varios campos de los documentos incrustados del arreglo. Se debe consultar Limitaciones del campo de arreglo para un ejemplo.
Las operaciones db.collection.find() en vistas no con compatibles con el operador de proyección $.
Comportamiento
Sintaxis
Para devolver el primer elemento del arreglo que coincida con la condición del query específica en el arreglo:
db.collection.find( { <array>: <condition> ... }, { "<array>.$": 1 } ) db.collection.find( { <array.field>: <condition> ...}, { "<array>.$": 1 } )
Puede utilizar el Operador $ para limitar un campo <array>, que no aparece en el documento de query. En versiones anteriores de MongoDB, el campo <array> que estaba limitado debía aparecer en el documento de query.
db.collection.find( { <someOtherArray>: <condition> ... }, { "<array>.$" : 1 } )
Importante
Para asegurar el comportamiento esperado, los arreglos utilizados en el documento del query y en el documento de proyección deben tener la misma longitud. Si los arreglos tienen longitudes diferentes, la operación puede arrojar un error en ciertos escenarios.
Limitaciones de los campos de arreglo
MongoDB requiere lo siguiente al tratar con proyección sobre arreglos:
Solo un operador posicional
$puede aparecer en el documento de proyección.Solo debes aparecer un campo de arreglo en el documento del query. Los [[arreglo]]s [[campo]]s adicionales en el [[documento]] del [[query]] pueden llevar a un comportamiento indefinido.
Por ejemplo, la siguiente proyección puede resultar en un comportamiento no definido:
db.collection.find( { <array>: <value>, <someOtherArray>: <value2> }, { "<array>.$": 1 } ) El documento del query solo debe contener una única condición en el campo de arreglo al que se aplica. Múltiples condiciones pueden superponerse internamente y llevar a un comportamiento indefinido.
Para especificar criterios en varios campos de documentos dentro de ese arreglo, utiliza el operador del query
$elemMatch. El siguiente query devuelve el primer documento dentro de un arreglogradesque tiene unmeanmayor que 70 y ungrademayor que 90.db.students.find( { grades: { $elemMatch: { mean: { $gt: 70 }, grade: { $gt:90 } } } }, { "grades.$": 1 } ) Debes usar el operador
$elemMatchsi necesitas condiciones separadas para seleccionar documentos y para elegir campos dentro de esos documentos.
Ordenaciones y el operador posicional
Cuando el método find() incluye un sort(), el método find() aplica el sort() para ordenar los documentos coincidentes antes aplicar el operador de proyección posicional $.
Si un campo de arreglo contiene múltiples documentos con el mismo nombre de campo y el método find() incluye un sort() en ese campo repetido, los documentos devueltos pueden no reflejar el orden de clasificación porque la clasificación se aplicó a los elementos del arreglo antes del operador de proyección $.
Restricción de colocación de operadores posicionales
El operador de proyección $ solo puede aparecer al final de la ruta de campo, por ejemplo "field.$" o "fieldA.fieldB.$".
Por ejemplo, la siguiente operación es inválida:
db.inventory.find( { }, { "instock.$.qty": 1 } )
Para resolver, elimine el componente de la ruta de campo que sigue al operador de proyección $.
Operador posicional $slice y restricción
find y findAndModify proyección no puede incluir la expresión de proyección $slice como parte de una expresión de proyección $.
Por ejemplo, la siguiente operación es inválida:
db.inventory.find( { "instock.qty": { $gt: 25 } }, { "instock.$": { $slice: 1 } } )
En versiones anteriores, MongoDB devuelve el primer elemento (instock.$) del arreglo instock que coincide con la condición de query; es decir, la proyección posicional "instock.$" tiene prioridad y la $slice:1 no realiza ninguna operación. El "instock.$": {
$slice: 1 } no excluye ningún otro campo del documento.
Ejemplos
Valores del arreglo del proyecto
Una colección students contiene los siguientes documentos:
db.students.insertMany( [ { _id : 1, "semester" : 1, "grades" : [ 70, 87, 90 ] }, { _id : 2, "semester" : 1, "grades" : [ 90, 88, 92 ] }, { _id : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] }, { _id : 4, "semester" : 2, "grades" : [ 79, 85, 80 ] }, { _id : 5, "semester" : 2, "grades" : [ 88, 88, 92 ] }, { _id : 6, "semester" : 2, "grades" : [ 95, 90, 96 ] } ] )
En el siguiente query, la proyección { "grades.$": 1 } devuelve solo el primer elemento que es mayor o igual a 85 para el campo grades.
db.students.find( { semester: 1, grades: { $gte: 85 } }, { "grades.$": 1 } )
La operación devuelve los siguientes documentos:
{ "_id" : 1, "grades" : [ 87 ] } { "_id" : 2, "grades" : [ 90 ] } { "_id" : 3, "grades" : [ 85 ] }
Aunque el campo de arreglo grades puede contener múltiples elementos que son mayores o iguales a 85, el operador de proyección $ devuelve solo el primer elemento coincidente del arreglo.
Documentos de arreglo del proyecto
Una colección students contiene los siguientes documentos, donde el campo grades es un arreglo de documentos; cada documento contiene los tres nombres de campo grade, mean y std:
db.students.insertMany( [ { _id : 7, semester: 3, "grades" : [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 90, mean: 85, std: 3 } ] }, { _id : 8, semester: 3, "grades" : [ { grade: 92, mean: 88, std: 8 }, { grade: 78, mean: 90, std: 5 }, { grade: 88, mean: 85, std: 3 } ] } ] )
En el siguiente query, la proyección { "grades.$": 1 } devuelve solo el primer elemento cuyo mean es mayor que 70 para el campo grades:
db.students.find( { "grades.mean": { $gt: 70 } }, { "grades.$": 1 } )
La operación devuelve los siguientes documentos:
{ "_id" : 7, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 } ] } { "_id" : 8, "grades" : [ { "grade" : 92, "mean" : 88, "std" : 8 } ] }