The $facet operator in the MongoDB aggregation framework is used to process multiple pipelines within a single stage. The $facet operator facilitates the execution of multiple aggregation pipelines within a single stage in the aggregation pipeline. The output from each sub-pipeline is returned as a named field in the output document.
Here is the basic syntax of the $facet operator:
{
$facet: {
<outputField1>: [ <aggregationPipeline1> ],
<outputField2>: [ <aggregationPipeline2> ],
...
}
}
In this syntax, the $facet operator takes an object that has multiple keys, with each key representing the name of the sub-pipeline that we want to execute. The value of each key is an array, and each element of the array represents one stage of the pipeline for the sub-pipeline.
Here’s an example that demonstrates the usage of the $facet operator. Let’s say we have a collection named "orders" that contains documents representing orders from an online retailer. Each order document contains fields such as the customer ID, order date, and order total.
Suppose we want to get the total revenue generated by the retailer in a given month, broken down by customer. We can use the $facet operator to execute two pipelines in parallel: one that groups the orders by customer ID and calculates the total revenue generated by each customer, and another that groups the orders by month and calculates the total revenue for each month. Here is how we can do this:
db.orders.aggregate([
{
$match: {
orderDate: {
$gte: ISODate('2021-01-01'),
$lte: ISODate('2021-01-31')
}
}
},
{
$facet: {
"byCustomer": [
{
$group: {
_id: "$customerId",
revenue: { $sum: "$orderTotal" }
}
}
],
"byMonth": [
{
$group: {
_id: { $month: "$orderDate" },
revenue: { $sum: "$orderTotal" }
}
}
]
}
}
])
In this example, we start by using a $match stage to filter the orders that were placed in the month of January 2021. Then, we use the $facet operator to execute two sub-pipelines in parallel. The "byCustomer" sub-pipeline uses the $group stage to group the orders by customer ID and calculate the total revenue generated by each customer. The "byMonth" sub-pipeline uses the $group stage to group the orders by month and calculate the total revenue generated in each month.
The output of the aggregation pipeline will be an array with one document, containing two fields - "byCustomer" and "byMonth". The value of each field will be an array with one document for each customer and each month, respectively, with the "_id" field containing the customer ID or the month number, and the "revenue" field containing the corresponding revenue. For example:
[
{
"byCustomer": [
{ "_id": "customer123", "revenue": 550 },
{ "_id": "customer456", "revenue": 250 },
...
],
"byMonth": [
{ "_id": 1, "revenue": 1800 }
]
}
]
In this output, we can see that customer123 generated $550 in revenue in January 2021, customer456 generated $250 in revenue in January 2021, and the retailer generated a total of $1800 in revenue in January 2021.