Docs Menu
Docs Home
/ /

$facet (etapa de agregación)

$facet

Procesos múltiples Canalizaciones de agregación dentro de una misma etapa en el mismo conjunto de documentos de entrada. Cada subcanalización tiene su propio campo en el documento de salida, donde sus resultados se almacenan como una matriz de documentos.

La etapa $facet le permite crear agregaciones multifacéticas que caracterizan los datos a través de múltiples dimensiones, o facetas, dentro de una única etapa de agregación. Las agregaciones multifacéticas ofrecen múltiples filtros y categorizaciones para orientar la exploración y el análisis de datos. Los minoristas suelen utilizar el facetado para acotar los resultados de búsqueda creando filtros en función del precio del producto, el fabricante, el tamaño, etc.

Los documentos de entrada se pasan a la etapa $facet una sola vez. $facet permite realizar varias agregaciones en el mismo conjunto de documentos de entrada, sin necesidad de recuperar los documentos de entrada múltiples veces.

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

La etapa $facet tiene la siguiente forma:

{ $facet:
{
<outputField1>: [ <stage1>, <stage2>, ... ],
<outputField2>: [ <stage1>, <stage2>, ... ],
...
}
}

Especifica el nombre del campo de salida para cada pipeline especificado.

A medida que se ejecuta cada etapa en un $facet, el documento resultante está limitado a 100 megabytes. Ten en cuenta que la bandera allowDiskUse no afecta el límite de tamaño de 100 megabytes, ya que $facet no puede volcarse en el disco.

El documento de salida final está sujeto al límite de tamaño de documento BSON de 16 mebibytes. Si se superan los 16 mebibytes, la agregación genera un error.

Tip

Las etapas de agregación relacionadas con facetas categorizan y agrupan los documentos entrantes. Especifica cualquiera de las siguientes etapas relacionadas con facetas dentro de los diferentes sub-pipelines $facet <stage> para realizar una agregación multifacética:

Otras etapas de agregación también pueden usarse con $facet con las siguientes excepciones:

Cada sub-pipeline dentro de $facet recibe exactamente el mismo conjunto de documentos de entrada. Estas sub-pipelines son completamente independientes entre sí y el arreglo de documentos generado por cada una se almacena en campos separados en el documento de salida. La salida de un sub-pipeline no puede usarse como entrada para un sub-pipeline diferente dentro de la misma etapa $facet. Si se requieren agregaciones adicionales, añade etapas adicionales después de $facet y especifica el nombre del campo, <outputField>, de la salida deseada del sub-pipeline.

El orden del pipeline determina cómo la etapa $facet utiliza los índices.

  • Si la etapa $facet es la primera etapa de un pipeline, la etapa realizará un COLLSCAN. La etapa $facet no utiliza índices si es la primera etapa en el pipeline.

  • Si la etapa $facet llega más adelante en el pipeline y las etapas anteriores han utilizado índices, $facet no activará un COLLSCAN durante la ejecución.

Por ejemplo, $match o $sort etapas que vienen antes de una etapa $facet pueden hacer uso de índices y el $facet no activará un COLLSCAN.

Para obtener sugerencias de optimización, consulta: Optimización de la canalización de agregación.

Considera un sistema para almacenar en línea cuyo inventario se almacena en la siguiente colección artwork:

{ "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926,
"price" : Decimal128("199.99"),
"tags" : [ "painting", "satire", "Expressionism", "caricature" ] }
{ "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902,
"price" : Decimal128("280.00"),
"tags" : [ "woodcut", "Expressionism" ] }
{ "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925,
"price" : Decimal128("76.04"),
"tags" : [ "oil", "Surrealism", "painting" ] }
{ "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai",
"price" : Decimal128("167.30"),
"tags" : [ "woodblock", "ukiyo-e" ] }
{ "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931,
"price" : Decimal128("483.00"),
"tags" : [ "Surrealism", "painting", "oil" ] }
{ "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913,
"price" : Decimal128("385.00"),
"tags" : [ "oil", "painting", "abstract" ] }
{ "_id" : 7, "title" : "The Scream", "artist" : "Munch", "year" : 1893,
"tags" : [ "Expressionism", "painting", "oil" ] }
{ "_id" : 8, "title" : "Blue Flower", "artist" : "O'Keefe", "year" : 1918,
"price" : Decimal128("118.42"),
"tags" : [ "abstract", "painting" ] }

La siguiente operación utiliza las características de facetas de MongoDB para proporcionar a los clientes el inventario del almacén categorizado en múltiples dimensiones como etiquetas, precio y año de creación. Esta $facet etapa tiene tres sub-pipelines que utilizan $sortByCount, $bucket, o $bucketAuto para realizar esta agregación multifacética. Los documentos de entrada de artwork se extraen de la base de datos solo una vez, al comienzo de la operación:

db.artwork.aggregate( [
{
$facet: {
"categorizedByTags": [
{ $unwind: "$tags" },
{ $sortByCount: "$tags" }
],
"categorizedByPrice": [
// Filter out documents without a price e.g., _id: 7
{ $match: { price: { $exists: 1 } } },
{
$bucket: {
groupBy: "$price",
boundaries: [ 0, 150, 200, 300, 400 ],
default: "Other",
output: {
"count": { $sum: 1 },
"titles": { $push: "$title" }
}
}
}
],
"categorizedByYears(Auto)": [
{
$bucketAuto: {
groupBy: "$year",
buckets: 4
}
}
]
}
}
])

La operación devuelve el siguiente documento:

{
"categorizedByYears(Auto)" : [
// First bucket includes the document without a year, e.g., _id: 4
{ "_id" : { "min" : null, "max" : 1902 }, "count" : 2 },
{ "_id" : { "min" : 1902, "max" : 1918 }, "count" : 2 },
{ "_id" : { "min" : 1918, "max" : 1926 }, "count" : 2 },
{ "_id" : { "min" : 1926, "max" : 1931 }, "count" : 2 }
],
"categorizedByPrice" : [
{
"_id" : 0,
"count" : 2,
"titles" : [
"Dancer",
"Blue Flower"
]
},
{
"_id" : 150,
"count" : 2,
"titles" : [
"The Pillars of Society",
"The Great Wave off Kanagawa"
]
},
{
"_id" : 200,
"count" : 1,
"titles" : [
"Melancholy III"
]
},
{
"_id" : 300,
"count" : 1,
"titles" : [
"Composition VII"
]
},
{
// Includes document price outside of bucket boundaries, e.g., _id: 5
"_id" : "Other",
"count" : 1,
"titles" : [
"The Persistence of Memory"
]
}
],
"categorizedByTags" : [
{ "_id" : "painting", "count" : 6 },
{ "_id" : "oil", "count" : 4 },
{ "_id" : "Expressionism", "count" : 3 },
{ "_id" : "Surrealism", "count" : 2 },
{ "_id" : "abstract", "count" : 2 },
{ "_id" : "woodblock", "count" : 1 },
{ "_id" : "woodcut", "count" : 1 },
{ "_id" : "ukiyo-e", "count" : 1 },
{ "_id" : "satire", "count" : 1 },
{ "_id" : "caricature", "count" : 1 }
]
}

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 $facet etapa a una canalización de agregación, llame a Facet()método en un PipelineDefinition objeto.

El siguiente ejemplo crea una etapa del pipeline que ejecuta dos agregaciones paralelas. La primera agregación distribuye los documentos entrantes en cinco grupos por el valor de su campo Runtime. La segunda agregación cuenta cada valor en el campo Rated y devuelve el recuento de cada valor, limitado a los cinco valores principales.

var bucketPipeline = new EmptyPipelineDefinition<Movie>()
.BucketAuto(
groupBy: m => m.Runtime,
buckets: 5);
var bucketFacet = AggregateFacet.Create(
name: "Runtimes",
pipeline: bucketPipeline);
var countLimitPipeline = new EmptyPipelineDefinition<Movie>()
.SortByCount(m => m.Rated)
.Limit(5);
var countFacet = AggregateFacet.Create(
"Ratings", countLimitPipeline);
var pipeline = new EmptyPipelineDefinition<Movie>()
.Facet(bucketFacet, countFacet);

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 $facet a una canalización de agregación, utilice el Operador $facet en un objeto de canalización.

El siguiente ejemplo crea una etapa del pipeline que ejecuta dos agregaciones paralelas. La primera agregación distribuye los documentos entrantes en cinco grupos según el valor de su campo runtime utilizando la etapa $bucketAuto. La segunda agregación cuenta cada valor en el campo rated y devuelve el recuento de los cinco valores principales utilizando las etapas $sortByCount y $limit. A continuación, el ejemplo ejecuta la canalización de agregación:

const pipeline = [
{
$facet: {
bucketPipeline: [
{
$bucketAuto: {
groupBy: "$runtime",
buckets: 5
}
}
],
countLimit: [
{ $sortByCount: "$rated" },
{ $limit: 5 }
]
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

Para obtener más información sobre las etapas relacionadas del pipeline, consulta las guías $bucketAuto, $sortByCount y $limit.

Volver

$documents

En esta página