Definición
Compatibilidad
Puedes usar $project 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
La etapa $project tiene la siguiente forma de prototipo:
{ $project: { <specification(s)> } }
El $project procesa un documento que puede especificar la inclusión de campos, la eliminación del campo _id, la adición de nuevos campos y el restablecimiento de los valores de los campos existentes. Alternativamente, puede especificarse la exclusión de campos.
Las especificaciones tienen las siguientes $project formas:
formulario | Descripción |
|---|---|
| Especifica la inclusión de un campo. Los enteros no nulos también se tratan como |
| Especifica la eliminación del campo Para excluir un campo de forma condicional, utiliza la variable |
| Añade un nuevo campo o restablece el valor de un campo existente. Si la expresión se evalúa como |
| Especifica la exclusión de un campo. Para excluir un campo de forma condicional, utiliza la variable Si especificas la exclusión de un campo distinto de Consultar también la |
Comportamiento
Incluir campos
El campo
_idse incluye, por defecto, en los documentos de salida. Para incluir cualquier otro campo de los documentos de entrada en los documentos de salida, debe especificar explícitamente la inclusión en$project.Si especificas la inclusión de un campo que no existe en el documento,
$projectignora esa inclusión y no añade el campo al documento.
_id Campo
Por defecto, el campo _id se incluye en los documentos de salida. Para excluir el campo _id de los documentos de salida, debe especificarse explícitamente la supresión del campo _id en $project.
Excluir campos
Si se especifica la exclusión de un campo o varios campos, todos los demás campos se devuelven en los documentos de salida.
{ $project: { "<field1>": 0, "<field2>": 0, ... } } // Return all but the specified fields
Si especificas la exclusión de un campo distinto de _id, no puedes emplear ninguna otra forma de especificación $project: es decir, si excluyes campos, no puedes especificar la inclusión de campos, restablecer el valor de campos existentes o agregar campos nuevos. Esta restricción no se aplica a la exclusión condicional de un campo usando la variable REMOVE.
Consultar también la $unset etapa para excluir campos.
Excluir campos de forma condicional
Puedes usar la variable REMOVE en expresiones de agregación para suprimir condicionalmente un campo. Para un ejemplo, ve Excluir campos condicionalmente.
Añadir nuevos campos o restablecer los campos existentes
Nota
MongoDB también proporciona $addFields para añadir nuevos campos a los documentos.
Para agregar un nuevo campo o restablecer el valor de un campo existente, especifique el nombre del campo y establezca su valor en alguna expresión. Para obtener más información sobre las expresiones, consulte Expresiones.
Valores literales
Para establecer el valor de un campo directamente en un literal numérico o booleano, en lugar de establecer el campo en una expresión que se resuelva en un literal, utilizar el operador $literal. De lo contrario, $project trata el literal numérico o booleano como un indicador para incluir o excluir el campo.
Renombrar campo
Al especificar un nuevo campo y establecer el valor en la ruta de campo de un campo existente, se puede renombrar un campo de manera efectiva.
Nuevos campos de arreglo
La etapa $project admite el uso de los corchetes [] para crear directamente nuevos campos de arreglo. Si especificas campos de arreglo que no existen en un documento, la operación sustituye null como valor de ese campo. Para ver un ejemplo, consulta Proyecto nuevos campos de arreglo.
No puedes utilizar un índice de arreglo con la etapa $project. Para obtener más información, consulta Los índices de arreglos no son compatibles.
Campos de documento incrustado
Al proyectar o añadir/restablecer un campo dentro de un documento incrustado, puede utilizar notación de puntos, como en
"contact.address.country": <1 or 0 or expression>
O puede anidar los campos:
contact: { address: { country: <1 or 0 or expression> } }
Al anidar los campos, no puedes utilizar la notación de puntos dentro del documento incrustado para especificar el campo, por ejemplo, contact: {
"address.country": <1 or 0 or expression> } es inválido.
Errores de colisión de rutas en campos incrustados
No puede especificar tanto un documento incrustado como un campo dentro de ese documento incrustado en la misma proyección.
La siguiente etapa $project falla con un error Path collision porque intenta proyectar tanto el documento incrustado contact como el campo contact.address.country:
{ $project: { contact: 1, "contact.address.country": 1 } }
El error ocurre independientemente del orden en que se especifiquen el documento principal y el campo incrustado. El siguiente $project falla con el mismo error:
{ $project: { "contact.address.country": 1, contact: 1 } }
$project Puesta en escena
Cuando se usa una etapa $project, normalmente debería ser la última etapa del pipeline, utilizada para especificar qué campos devolver al cliente.
Usar una etapa $project al principio o en la mitad de una pipeline para reducir la cantidad de campos pasados a las siguientes etapas de la pipeline probablemente no mejorará el rendimiento, ya que la base de datos realiza automáticamente esta optimización.
Considerations
Especificación vacía
MongoDB devuelve un error si a la etapa $project se le pasa un documento vacío.
Por ejemplo, ejecutar la siguiente pipeline produce un error:
db.myCollection.aggregate( [ { $project: { } } ] )
Array Index
No puedes utilizar un índice de arreglo con la etapa $project. Para obtener más información, consulta Los índices de arreglos no son compatibles.
Ejemplos
Incluir campos específicos en los documentos de salida
Considere una colección books con el siguiente documento:
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5 }
La siguiente $project etapa incluye solo los campos _id, title y el author en sus documentos de salida:
db.books.aggregate( [ { $project : { title : 1 , author : 1 } } ] )
La operación produce el siguiente documento:
{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
Suprimir el campo _id en los documentos de salida
El campo _id siempre se incluye por defecto. Para excluir el campo _id de los documentos de salida de la etapa $project, especifique la exclusión del campo _id configurándolo en 0 en el documento de proyección.
Considere una colección books con el siguiente documento:
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5 }
La siguiente $project etapa excluye el campo _id pero incluye los campos title y author en sus documentos de salida:
db.books.aggregate( [ { $project : { _id: 0, title : 1 , author : 1 } } ] )
La operación produce el siguiente documento:
{ "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
Excluir campos de los documentos de salida
Considere una colección books con el siguiente documento:
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5, lastModified: "2016-07-28" }
La siguiente $project etapa excluye el campo lastModified de la salida:
db.books.aggregate( [ { $project : { "lastModified": 0 } } ] )
Consultar también la $unset etapa para excluir campos.
Excluir campos de documentos incrustados
Considere una colección books con el siguiente documento:
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5, lastModified: "2016-07-28" }
La siguiente etapa $project excluye los campos author.first y lastModified de la salida:
db.books.aggregate( [ { $project : { "author.first" : 0, "lastModified" : 0 } } ] )
Alternativamente, se puede anidar la especificación de exclusión en un documento:
db.bookmarks.aggregate( [ { $project: { "author": { "first": 0}, "lastModified" : 0 } } ] )
Ambas especificaciones producen el mismo resultado:
{ "_id" : 1, "title" : "abc123", "isbn" : "0001122223334", "author" : { "last" : "zzz" }, "copies" : 5, }
Consultar también la $unset etapa para excluir campos.
Excluir campos condicionalmente
Puedes usar la variable REMOVE en expresiones de agregación para suprimir condicionalmente un campo.
Considere una colección books con el siguiente documento:
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5, lastModified: "2016-07-28" } { "_id" : 2, title: "Baked Goods", isbn: "9999999999999", author: { last: "xyz", first: "abc", middle: "" }, copies: 2, lastModified: "2017-07-21" } { "_id" : 3, title: "Ice Cream Cakes", isbn: "8888888888888", author: { last: "xyz", first: "abc", middle: "mmm" }, copies: 5, lastModified: "2017-07-22" }
La siguiente $project etapa utiliza la variable REMOVE para excluir el campo author.middle solo si es igual a "":
db.books.aggregate( [ { $project: { title: 1, "author.first": 1, "author.last" : 1, "author.middle": { $cond: { if: { $eq: [ "", "$author.middle" ] }, then: "$$REMOVE", else: "$author.middle" } } } } ] )
La operación de agregación da el siguiente resultado:
{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } } { "_id" : 2, "title" : "Baked Goods", "author" : { "last" : "xyz", "first" : "abc" } } { "_id" : 3, "title" : "Ice Cream Cakes", "author" : { "last" : "xyz", "first" : "abc", "middle" : "mmm" } }
Tip
Comparación con $addFields
Puedes usar la plataforma $addFields o $project para remover campos de documentos. El mejor enfoque depende de su pipeline y de cuánto del documento original desea conservar.
Para ver un ejemplo de uso de $$REMOVE en una etapa $addFields, consulte Remover campos.
Incluir campos específicos de documentos incrustados
Considera una colección bookmarks con los siguientes documentos:
{ _id: 1, user: "1234", stop: { title: "book1", author: "xyz", page: 32 } } { _id: 2, user: "7890", stop: [ { title: "book2", author: "abc", page: 5 }, { title: "book3", author: "ijk", page: 100 } ] }
Para incluir solo el campo title en el documento incrustado en el campo stop, puede utilizarse la notación de puntos:
db.bookmarks.aggregate( [ { $project: { "stop.title": 1 } } ] )
O puede anidar la especificación de inclusión en un documento:
db.bookmarks.aggregate( [ { $project: { stop: { title: 1 } } } ] )
Ambas especificaciones resultan en los siguientes documentos:
{ "_id" : 1, "stop" : { "title" : "book1" } } { "_id" : 2, "stop" : [ { "title" : "book2" }, { "title" : "book3" } ] }
Incluir campos calculados
Considere una colección books con el siguiente documento:
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5 }
La siguiente $project etapa agrega los nuevos campos isbn, lastName y copiesSold:
db.books.aggregate( [ { $project: { title: 1, isbn: { prefix: { $substr: [ "$isbn", 0, 3 ] }, group: { $substr: [ "$isbn", 3, 2 ] }, publisher: { $substr: [ "$isbn", 5, 4 ] }, title: { $substr: [ "$isbn", 9, 3 ] }, checkDigit: { $substr: [ "$isbn", 12, 1] } }, lastName: "$author.last", copiesSold: "$copies" } } ] )
La operación produce el siguiente documento:
{ "_id" : 1, "title" : "abc123", "isbn" : { "prefix" : "000", "group" : "11", "publisher" : "2222", "title" : "333", "checkDigit" : "4" }, "lastName" : "zzz", "copiesSold" : 5 }
Proyecto de nuevos campos de arreglo
Por ejemplo, si una colección incluye el siguiente documento:
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "x" : 1, "y" : 1 }
La siguiente operación proyecta los campos x y y como elementos en un nuevo campo myArray:
db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y" ] } } ] )
La operación devuelve el siguiente documento:
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1 ] }
Si la especificación de la matriz incluye campos que no existen en un documento, la operación sustituye null como valor para ese campo.
Por ejemplo, dado el mismo documento que antes, la siguiente operación proyecta los campos x, y y un campo inexistente $someField como elementos en un nuevo campo myArray:
db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y", "$someField" ] } } ] )
La operación devuelve el siguiente documento:
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1, null ] }
Los índices de arreglos no son compatibles
No puede utilizar un índice de arreglo con la etapa $project. Esta sección muestra un ejemplo.
Cree la siguiente colección pizzas:
db.pizzas.insert( [ { _id: 0, name: [ 'Pepperoni' ] }, ] )
El siguiente ejemplo devuelve la pizza:
db.pizzas.aggregate( [ { $project: { x: '$name', _id: 0 } }, ] )
La pizza se devuelve en el resultado del ejemplo:
[ { x: [ 'Pepperoni' ] } ]
El siguiente ejemplo utiliza un índice de arreglo ($name.0) para intentar devolver la pizza:
db.pizzas.aggregate( [ { $project: { x: '$name.0', _id: 0 } }, ] )
La pizza no se incluye en la salida del ejemplo:
[ { x: [] } ]