Docs HomeMongoDB Manual

$facet (aggregation)

Definition定义

$facet

Processes multiple aggregation pipelines within a single stage on the same set of input documents. 在同一组输入文档的单个阶段内处理多个聚合管道Each sub-pipeline has its own field in the output document where its results are stored as an array of documents.每个子管道在输出文档中都有自己的字段,其结果存储为文档数组。

The $facet stage allows you to create multi-faceted aggregations which characterize data across multiple dimensions, or facets, within a single aggregation stage. $facet阶段允许您创建多方面聚合,这些聚合在单个聚合阶段内表征多个维度或方面的数据。Multi-faceted aggregations provide multiple filters and categorizations to guide data browsing and analysis. 多面聚合提供了多个筛选器和分类,以指导数据浏览和分析。Retailers commonly use faceting to narrow search results by creating filters on product price, manufacturer, size, etc.零售商通常通过对产品价格、制造商、尺寸等进行筛选来缩小搜索结果。

Input documents are passed to the $facet stage only once. 输入文档只传递到$facet阶段一次。$facet enables various aggregations on the same set of input documents, without needing to retrieve the input documents multiple times.$facet允许对同一组输入文档进行各种聚合,而无需多次检索输入文档。

The $facet stage has the following form:$facet阶段具有以下形式:

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

}
}

Specify the output field name for each specified pipeline.为每个指定的管道指定输出字段名称。

Considerations注意事项

The output of the $facet stage is subject to the 16 megabyte BSON Document Size limit. $facet阶段的输出受16兆字节BSON文档大小限制If the results of the $facet stage exceed the BSON Document Size limit, the aggregation produces an error.如果$facet阶段的结果超过BSON文档大小限制,则聚合会产生错误。

Tip

Behavior行为

Facet-related aggregation stages categorize and group incoming documents. 与Facet相关的聚合阶段对传入文档进行分类和分组。Specify any of the following facet-related stages within different $facet sub-pipeline's <stage> to perform a multi-faceted aggregation:在不同$facet子管道的<stage>中指定以下任何与facet相关的阶段,以执行多方面聚合:

Other aggregation stages can also be used with $facet with the following exceptions:除了以下例外,其他聚合阶段也可以与$facet一起使用:

Each sub-pipeline within $facet is passed the exact same set of input documents. $facet中的每个子管道都传递完全相同的一组输入文档。These sub-pipelines are completely independent of one another and the document array output by each is stored in separate fields in the output document. 这些子管道彼此完全独立,并且每个子管道输出的文档数组存储在输出文档中的单独字段中。The output of one sub-pipeline can not be used as the input for a different sub-pipeline within the same $facet stage. 一个子管道的输出不能用作同一$facet阶段内不同子管道的输入。If further aggregations are required, add additional stages after $facet and specify the field name, <outputField>, of the desired sub-pipeline output.如果需要进一步聚合,请在$facet之后添加其他阶段,并指定所需子管道输出的字段名<outputField>

Index Use索引使用

Pipeline order determines how the $facet stage uses indexes.管道顺序决定$facet阶段如何使用索引。

  • If the $facet stage is the first stage in a pipeline, the stage will perform a COLLSCAN. The $facet stage does not make use of indexes if it is the first stage in the pipeline.如果$facet阶段是管道中的第一个阶段,则该阶段将执行COLLSCAN。如果$facet阶段是管道中的第一个阶段,则它不使用索引。
  • If the $facet stage comes later in the pipeline and earlier stages have used indexes, $facet will not trigger a COLLSCAN during execution.如果$facet阶段在管道的后面,并且前面的阶段使用了索引,那么$facet在执行期间将不会触发COLLSCAN

For example, $match or $sort stages that come before a $facet stage can make use of indexes and the $facet will not trigger a COLLSCAN.例如,$facet阶段之前的$match$sort阶段可以使用索引,而$facet不会触发COLLSCAN

For optimization suggestions, see: Aggregation Pipeline Optimization.有关优化建议,请参阅:聚合管道优化

Example实例

Consider an online store whose inventory is stored in the following artwork collection:考虑一个在线商店,其库存存储在以下artwork集合中:

{ "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926,
"price" : NumberDecimal("199.99"),
"tags" : [ "painting", "satire", "Expressionism", "caricature" ] }
{ "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902,
"price" : NumberDecimal("280.00"),
"tags" : [ "woodcut", "Expressionism" ] }
{ "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925,
"price" : NumberDecimal("76.04"),
"tags" : [ "oil", "Surrealism", "painting" ] }
{ "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai",
"price" : NumberDecimal("167.30"),
"tags" : [ "woodblock", "ukiyo-e" ] }
{ "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931,
"price" : NumberDecimal("483.00"),
"tags" : [ "Surrealism", "painting", "oil" ] }
{ "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913,
"price" : NumberDecimal("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" : NumberDecimal("118.42"),
"tags" : [ "abstract", "painting" ] }

The following operation uses MongoDB's faceting features to provide customers with the store's inventory categorized across multiple dimensions such as tags, price, and year created. 以下操作使用MongoDB的faceting功能为客户提供商店的库存,这些库存在标签、价格和创建年份等多个维度上进行了分类。This $facet stage has three sub-pipelines that use $sortByCount, $bucket, or $bucketAuto to perform this multi-faceted aggregation. 这个$facet阶段有三个子管道,它们使用$sortByCount$bucket$bucketAuto来执行这个多方面聚合。The input documents from artwork are fetched from the database only once, at the beginning of the operation:在操作开始时,仅从数据库中提取一次来自artwork的输入文档:

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
}
}
]
}
}
])

The operation returns the following document:该操作返回以下文档:

{
"categorizedByYears(Auto)" : [
// First bucket includes the document without a year,第一个bucket包括没有年份的文档, 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 }
]
}