Aggregation
Overview
In this guide, you can learn how to use aggregation operations in the MongoDB Go Driver.
Aggregation operations process data in your MongoDB collections based on your specifications in the aggregation pipeline. An aggregation pipeline consists of one or more stages. Each stage performs an operation based on its expression operators. After the driver executes the aggregation pipeline, it returns an aggregated result.
Analogy
Aggregation operations operate similarly to a car factory. Car factories have an assembly line. The assembly lines have assembly stations with specialized tools to perform a specific task. To build a car, you send raw parts to the factory. Then, the assembly line transforms and assembles the parts into a car.
The assembly line resembles the aggregation pipeline, the assembly stations in the assembly line resemble the aggregation stages, the specialized tools represent the expression operators, and the finished product resembles the aggregated result.
Compare Operations
The following table lists the tasks you can perform by using find and aggregation operations.
Find Operations | Aggregation Operations |
---|---|
Select what documents to return Select which fields to return Sort the results Limit the results Count the results | Select what documents to return Select which fields to return Sort the results Limit the results Count the results Rename fields Calculate fields Summarize data Group values |
Limitations
Aggregation operations have limitations. When performing aggregation operations, keep the following in mind:
Returned documents must not violate the BSON document size limit of 16 megabytes.
Pipeline stages have a memory limit of 100 megabytes by default. If required, you may exceed this limit by using the allowDiskUse method.
The $graphLookup stage has a strict memory limit of 100 megabytes and ignores
allowDiskUse
.
Examples
The examples in this section use the following Tea
struct as a model for documents
in the tea
collection:
type Tea struct { Type string Category string Toppings []string Price float32 }
To run the examples in this section, load the sample data into the
tea
collection in the db
database by using the following snippet:
coll := client.Database("db").Collection("tea") docs := []interface{}{ Tea{Type: "Masala", Category: "black", Toppings: []string{"ginger", "pumpkin spice", "cinnamon"}, Price: 6.75}, Tea{Type: "Gyokuro", Category: "green", Toppings: []string{"berries", "milk foam"}, Price: 5.65}, Tea{Type: "English Breakfast", Category: "black", Toppings: []string{"whipped cream", "honey"}, Price: 5.75}, Tea{Type: "Sencha", Category: "green", Toppings: []string{"lemon", "whipped cream"}, Price: 5.15}, Tea{Type: "Assam", Category: "black", Toppings: []string{"milk foam", "honey", "berries"}, Price: 5.65}, Tea{Type: "Matcha", Category: "green", Toppings: []string{"whipped cream", "honey"}, Price: 6.45}, Tea{Type: "Earl Grey", Category: "black", Toppings: []string{"milk foam", "pumpkin spice"}, Price: 6.15}, Tea{Type: "Hojicha", Category: "green", Toppings: []string{"lemon", "ginger", "milk foam"}, Price: 5.55}, } result, err := coll.InsertMany(context.TODO(), docs)
Each document contains information about the tea type, the available toppings, and the price.
Average Rating
The following example calculates and displays the average rating and number of ratings for each tea category.
The aggregation pipeline uses the $group
stage to group the
documents by the category
field, calculates the average using the
$avg
expression operator, and counts the number of documents using
the $sum
expression operator.
// create group stage groupStage := bson.D{ {"$group", bson.D{ {"_id", "$category"}, {"average_price", bson.D{{"$avg", "$price"}}}, {"type_total", bson.D{{"$sum", 1}}}, }}} // pass the pipeline to the Aggregate() method cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{groupStage}) if err != nil { panic(err) } // display the results var results []bson.M if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { fmt.Printf("Average price of %v tea options: $%v \n", result["_id"], result["average_price"]) fmt.Printf("Number of %v tea options: %v \n\n", result["_id"], result["type_total"]) }
Average price of black tea options: $6.075 Number of black tea options: 4 Average price of green tea options: $5.70 Number of green tea options: 4
Omit Fields in Results
The following example matches documents where you can get milk foam as a topping and lists the two cheapest options.
The aggregation pipeline contains the following stages:
$match
stage to match documents where thetoppings
field contains "milk foam"$unset
stage to omit the_id
andcategory
fields$sort
stage to sort theprice
andtoppings
in ascending order$limit
stage to show the first two documents
// create the stages matchStage := bson.D{{"$match", bson.D{{"toppings", "milk foam"}}}} unsetStage := bson.D{{"$unset", bson.A{"_id", "category"}}} sortStage := bson.D{{"$sort", bson.D{{"price", 1}, {"toppings", 1}}}} limitStage := bson.D{{"$limit", 2}} // pass the pipeline to the Aggregate() method cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{matchStage, unsetStage, sortStage, limitStage}) if err != nil { panic(err) } // display the results var results []Tea if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { fmt.Printf("Tea: %v \nToppings: %v \nPrice: $%v \n\n", result.Type, strings.Join(result.Toppings, ", "), result.Price) }
Tea: Hojicha Toppings: lemon, ginger, milk foam Price: $5.55 Tea: Gyokuro Toppings: berries, milk foam Price: $5.65
Additional Information
To learn more about the terms mentioned, see the following guides:
To view more aggregation examples, see the following guides:
To learn more about the Aggregate()
method and its behavior, see
Retrieve Data.
API Documentation
To learn more about any of the methods or types discussed in this guide, see the following API Documentation: