Para agentes de IA: hay un índice de documentación disponible en https://www.mongodb.com/es/docs/llms.txt — versiones en markdown de todas las páginas están disponibles agregando .md a cualquier ruta URL.
See how MongoDB 9.0 delivers up to 2x higher throughput.
MongoDB Branding Shape
Register now >
Docs Menu

$unwind (etapa de agregación)

$unwind

Descompone un campo de arreglo de los documentos de entrada para producir un documento para cada elemento. Cada documento de salida es el documento de entrada con el valor del campo del arreglo reemplazado por el elemento.

Puedes usar $unwind 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.

Para desenrollar un campo de matriz, pase un operando de ruta de campo o un operando de documento.

Puedes pasar la ruta del campo de matriz a $unwind. Con esta sintaxis, $unwind no genera un documento si el valor del campo es nulo, falta o es una matriz vacía.

{ $unwind: <field path> }

Cuando especifiques la ruta de campo, antepón el nombre del campo con un signo de dólar $ y enciérralo entre comillas.

Puedes pasar un documento a $unwind para especificar opciones.

{
$unwind:
{
path: <field path>,
includeArrayIndex: <string>,
preserveNullAndEmptyArrays: <boolean>
}
}
Campo
Tipo
Descripción

string

Ruta de campo a un campo de arreglo. Para especificar una ruta de campo, anteponer el nombre del campo con un signo de dólar $ y encerrarlo entre comillas.

string

Opcional. El nombre de un nuevo campo para contener el índice del arreglo del elemento. El nombre no puede comenzar con un signo de dólar $.

booleano

Opcional.

  • Si true, si path falta o es un arreglo vacío, $unwind omite el campo de salida del documento de salida. Si el valor es null, el campo permanece null.

  • Si false, si path es nulo, falta o es un arreglo vacío, $unwind no genera un documento.

El valor por defecto es false.

Cuando el valor en path no se resuelve en un arreglo, $unwind se comporta de la siguiente manera:

  • Si el valor no falta, no es null y no es un arreglo vacío, $unwind genera un solo documento utilizando el valor tal cual.

  • Si includeArrayIndex se especifica, el índice es 0 para entradas de arreglos y null para entradas que no sean de arreglos. Los documentos posteriores en la lista tienen un índice superior a 0.

  • Si falta el valor, null, o es un arreglo vacío, $unwind sigue la opción preserveNullAndEmptyArrays. Cuando se especifica includeArrayIndex y se conserva el documento, el índice es null.

Si especifica una ruta para un campo que no existe en un documento de entrada o el campo es una matriz vacía, $unwind, por defecto, ignora el documento de entrada y no generará documentos para ese documento de entrada.

Para generar documentos donde el campo de matriz no esté presente, sea nulo o sea una matriz vacía, utilice la opción preserveNullAndEmptyArrays.

Los ejemplos de esta página utilizan datos del conjunto de datos sample_mflix. Para obtener más información sobre cómo cargar este conjunto de datos en su implementación autogestionada de MongoDB, consulte Cargar el conjunto de datos de ejemplo. Si realizó alguna modificación en las bases de datos de ejemplo, es posible que deba eliminarlas y volver a crearlas para ejecutar los ejemplos de esta página.

La siguiente agregación utiliza la etapa $unwind para generar un documento para cada elemento en la matriz genres del documento de película Inception:

db.movies.aggregate( [
{ $match: { title: "Inception" } },
{ $project: { _id: 0, title: 1, genres: 1 } },
{ $unwind: "$genres" }
] )
[
{
genres: 'Action',
title: 'Inception'
},
{
genres: 'Mystery',
title: 'Inception'
},
{
genres: 'Sci-Fi',
title: 'Inception'
}
]

Cada documento de salida es idéntico al documento de entrada, excepto por el valor del campo genres, que ahora contiene un solo elemento del array original genres.

La siguiente agregación utiliza la etapa $unwind con cuatro documentos de películas. Dos de los documentos ("La porta del cielo" y "Neecha Nagar") no tienen un campo genres:

db.movies.aggregate( [
{
$match: {
title: {
$in: [
"Inception",
"Brave",
"La porta del cielo",
"Neecha Nagar"
]
}
}
},
{ $project: { _id: 0, title: 1, genres: 1 } },
{ $unwind: { path: "$genres" } }
] )
[
{
genres: 'Animation',
title: 'Brave'
},
{
genres: 'Adventure',
title: 'Brave'
},
{
genres: 'Comedy',
title: 'Brave'
},
{
genres: 'Action',
title: 'Inception'
},
{
genres: 'Mystery',
title: 'Inception'
},
{
genres: 'Sci-Fi',
title: 'Inception'
}
]
  • En los documentos "Brave" y "Inception", genres es un array con datos. $unwind devuelve un documento para cada elemento.

  • Los documentos "La porta del cielo" y "Neecha Nagar" no tienen un campo genres, por lo que $unwind no devuelve ningún documento para ellos.

Nota

La sintaxis { path: <FIELD> } es opcional. Las siguientes operaciones $unwind son equivalentes.

db.<COLLECTION>.aggregate(
[ { $unwind: "<FIELD>" } ]
)
db.<COLLECTION>.aggregate(
[ { $unwind: { path: "<FIELD>" } } ]
)

Los ejemplos preserveNullAndEmptyArrays e includeArrayIndex utilizan documentos de la colección sample_mflix.movies.

La siguiente operación $unwind utiliza la opción preserveNullAndEmptyArrays para incluir documentos cuyo campo genres no está presente.

db.movies.aggregate( [
{
$match: {
title: {
$in: [
"Inception",
"Brave",
"La porta del cielo",
"Neecha Nagar"
]
}
}
},
{ $project: { _id: 0, title: 1, genres: 1 } },
{
$unwind: {
path: "$genres",
preserveNullAndEmptyArrays: true
}
}
] )
[
{
title: 'La porta del cielo'
},
{
title: 'Neecha Nagar'
},
{
genres: 'Animation',
title: 'Brave'
},
{
genres: 'Adventure',
title: 'Brave'
},
{
genres: 'Comedy',
title: 'Brave'
},
{
genres: 'Action',
title: 'Inception'
},
{
genres: 'Mystery',
title: 'Inception'
},
{
genres: 'Sci-Fi',
title: 'Inception'
}
]

La siguiente operación $unwind utiliza la opción includeArrayIndex para incluir el índice de la matriz en la salida.

db.movies.aggregate( [
{ $match: { title: "Inception" } },
{ $project: { _id: 0, title: 1, genres: 1 } },
{
$unwind: {
path: "$genres",
includeArrayIndex: "genreIndex"
}
}
] )
[
{
genres: 'Action',
title: 'Inception',
genreIndex: Long('0')
},
{
genres: 'Mystery',
title: 'Inception',
genreIndex: Long('1')
},
{
genres: 'Sci-Fi',
title: 'Inception',
genreIndex: Long('2')
}
]

El siguiente proceso descompone el array genres y agrupa los documentos resultantes por género para contar el número de películas en cada género:

db.movies.aggregate( [
// First Stage
{
$match: {
title: {
$in: [
"The Dark Knight",
"Inception",
"Interstellar",
"Brave"
]
}
}
},
// Second Stage
{ $project: { _id: 0, title: 1, genres: 1 } },
// Third Stage
{ $unwind: "$genres" },
// Fourth Stage
{
$group: {
_id: "$genres",
movieCount: { $sum: 1 }
}
},
// Fifth Stage
{ $sort: { movieCount: -1 } }
] )
[
{
_id: 'Adventure',
movieCount: 2
},
{
_id: 'Action',
movieCount: 2
},
{
_id: 'Drama',
movieCount: 2
},
{
_id: 'Sci-Fi',
movieCount: 2
},
{
_id: 'Crime',
movieCount: 1
},
{
_id: 'Animation',
movieCount: 1
},
{
_id: 'Comedy',
movieCount: 1
},
{
_id: 'Mystery',
movieCount: 1
}
]

Puedes aplicar $unwind varias veces en una sola secuencia para expandir documentos que contienen varios campos de matriz. La siguiente operación desenrolla la matriz genres y luego la matriz cast para producir un documento plano para cada combinación de género y actor, y luego agrupa por género para contar el total de apariciones del elenco en cada género:

db.movies.aggregate( [
// First Stage
{
$match: {
title: {
$in: [ "Inception", "The Dark Knight", "Interstellar" ]
}
}
},
// Second Stage
{ $project: { _id: 0, title: 1, genres: 1, cast: 1 } },
// Third Stage
{ $unwind: "$genres" },
// Fourth Stage
{ $unwind: "$cast" },
// Fifth Stage
{
$group: {
_id: "$genres",
castAppearances: { $sum: 1 }
}
}
] )
[
{
_id: 'Adventure',
castAppearances: 4
},
{
_id: 'Crime',
castAppearances: 4
},
{
_id: 'Action',
castAppearances: 8
},
{
_id: 'Drama',
castAppearances: 8
},
{
_id: 'Mystery',
castAppearances: 4
},
{
_id: 'Sci-Fi',
castAppearances: 8
}
]

Los ejemplos de C# en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulta Primeros pasos en la documentación del controlador de MongoDB .NET/C#.

La siguiente clase Movie modela los documentos en la colección sample_mflix.movies:

public class Movie
{
public ObjectId Id { get; set; }
public int Runtime { get; set; }
public string Title { get; set; }
public string Rated { get; set; }
public List<string> Genres { get; set; }
public string Plot { get; set; }
public ImdbData Imdb { get; set; }
public int Year { get; set; }
public int Index { get; set; }
public string[] Comments { get; set; }
[BsonElement("lastupdated")]
public DateTime LastUpdated { get; set; }
}

Nota

ConventionPack para Pascal Case

Las clases de C# en esta página utilizan Pascal case para los nombres de sus propiedades, pero los nombres de los campos en la colección de MongoDB utilizan camel case. Para tener en cuenta esta diferencia, se puede usar el siguiente código para registrar un ConventionPack cuando la aplicación se inicie:

var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);

Para usar el controlador MongoDB.NET/C# para agregar una $unwind etapa a una canalización de agregación, llame al método Unwind() en un PipelineDefinition objeto.

El siguiente ejemplo crea una plataforma de pipeline que itera sobre el campo Genres en cada documento Movie de entrada. Para cada valor en el campo Genres, la plataforma crea un nuevo documento Movie y rellena su campo Genres con el valor Genres del documento de entrada.

var pipeline = new EmptyPipelineDefinition<Movie>()
.Unwind(m => m.Genres);

Puedes usar un objeto AggregateUnwindOptions para personalizar el comportamiento del método Unwind().

El siguiente ejemplo realiza la misma operación que el ejemplo anterior, pero también incluye las siguientes opciones:

  • PreserveNullAndEmptyArrays asegura que los documentos que contienen un arreglo vacío en el campo Genres se incluyan en el resultado.

  • La opción IncludeArrayIndex agrega un nuevo campo llamado Index a cada documento de salida. El valor de este campo es el índice del valor del campo Genres en el arreglo Genres del documento de entrada.

var pipeline = new EmptyPipelineDefinition<Movie>()
.Unwind(m => m.Genres,
new AggregateUnwindOptions<Movie>()
{
PreserveNullAndEmptyArrays = true,
IncludeArrayIndex = new ExpressionFieldDefinition<Movie, int>(
m => m.Index)
});

Los ejemplos de Node.js en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulte Primeros pasos en la documentación del controlador de MongoDB Node.js.

Para utilizar el controlador de MongoDB Node.js para agregar una etapa de $unwind a una canalización de agregación, utilice el Operador $unwind en un objeto de canalización.

El siguiente ejemplo crea una plataforma de pipeline que itera sobre el campo genres en cada documento movie de entrada. Para cada valor en el campo genres, la plataforma crea un nuevo documento movie y rellena su campo genres con el valor genres del documento de entrada. A continuación, el ejemplo ejecuta el pipeline de agregación:

const pipeline = [{ $unwind: "$genres" }];
const cursor = collection.aggregate(pipeline);
return cursor;

Puedes personalizar el comportamiento del método $unwind. El siguiente ejemplo realiza la misma operación que el ejemplo anterior, pero también incluye las siguientes opciones:

  • preserveNullAndEmptyArrays asegura que los documentos que contienen un arreglo vacío en el campo genres se incluyan en el resultado.

  • includeArrayIndex añade un nuevo campo llamado index a cada documento de salida. El campo contiene el índice del arreglo del valor genres en el campo genres del documento de entrada.

const pipeline = [
{
$unwind: {
path: "$genres",
preserveNullAndEmptyArrays: true,
includeArrayIndex: "index"
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

Para etapas y expresiones relacionadas, consulte $group, $sum, $sort y $multiply.

Para ver un ejemplo completo, consulte el tutorial "Desenrollar matrices y agrupar datos".