Aggregation Framework
Estimated time to read: 3 minutes
The Aggregation Framework in its simplest form is another way to query data in MongoDB. Everything that can be done via the MQL can also be done via the Aggregation Framework.
Syntax¶
Find all documents that have Wifi as one of the amenities. Only including price and address in the resulting cursor.
Using MQL, the following command could be used:
Using the Aggregation Framework, the following command could be used to produce the same results:
db.listingsAndReviews.aggregate(
[
{ $match: {"amenities": "Wifi" } },
{ $project: { "price": 1, "address": 1, "_id": 0 } }
]
)
The usage of the aggregate
command allows for grouping and aggregation of documents. It also allows operations other than finding and projecting data, it can also be used for counting documents.
Syntax Breakdown¶
db.listingsAndReviews.aggregate(
[
{ $match: {"amenities": "Wifi" } },
{ $project: { "price": 1, "address": 1, "_id": 0 } }
]
)
-
The
aggregate
command is used to tell MongoDB to use the specified method. -
An array is then created within the aggregation command.
-
Remember that the order of elements is important! Elements are accessed by knowing their position in the array.
-
The Aggregation Framework works as a pipeline, where the order of actions in the pipeline matters. Each action is executed in the order listed.
-
The transformed data is then returned at the end of the pipeline as an output.
Pipeline¶
Looking at the syntax above, it can be read as two separate filters.
The first filter is the $match
stage. This acts as a filter that keeps all the amenities without Wi-Fi from passing through to the next stage of the pipeline.
The second filter is the $project
stage. This acts as a filter to filter out all of the files that are not address or price from each document. It must be even finer filter than the first.
For each stage, specify what you want to do and pass this into the next stage to be acted upon.
Beyond MQL using $group¶
There are many stages that differentiate between MQL and the Aggregation Framework. One of these is the $group
stage. With MQL, data can be filtered or updated. With the Aggregation Framework, data can be computed and reshaped.
$group
is an operators that takes the incoming stream of data and siphons into multiple distinct reservoirs.
%%{init: {'flowchart' : {'curve' : 'cardinal'}}}%%
flowchart
data(Data)
match[$match]
group{$group}
A[Data A]
B[Data B]
C[Data C]
D[Data D]
data ==> match
match ==> group
group --> A
group --> B
group --> C
group --> D
Note
The non-filtering stages within the Aggregation Framework do not modify the original data when they do summaries, calculations and groupings of data. Instea, they work with the data that they get from the previous stage in the pipeline, which is in its own cursor.
$group Syntax¶
{
"$group": {
"_id": <expression>, // Group by expression. Identifies the group that the document belongs to.
<field1>: { < accumulator1> : <expression1> }
}
}
The first part of the $group
syntax allows for identifying a group that the document belongs to. This can be done using dot-notation.
The second part of the $group
syntax allows for more quantitative analysis of the data that is being passed through the pipeline.
$group Example¶
Find one document in the collection and only include the address field in the resulting cursor.
Project only the address field value for each document, then group all documents into one document per address.country value.
db.listingsAndReviews.aggregate([ { "$project": { "address": 1, "_id": 0 }},
{ "$group": { "_id": "$address.country" }}])
Project only the address field value for each document, then group all documents into one document per address.country value, and count one for each document in each group.
db.listingsAndReviews.aggregate([
{ "$project": { "address": 1, "_id": 0 }},
{ "$group": { "_id": "$address.country",
"count": { "$sum": 1 } } }
])
In the example above, the $group
command does the following:
{
"$group": // Using the $group command
{
"_id": "$address.country", // Identify a group that the document belongs to within the collection
"count": { "$sum": 1 } // Create new field, named sum, for documents that are created in the pipeline.
// $sum is then used to add 1 to each document that folds into each group
}
}