聚合(Aggregation)
Overview
在本指南中,您可了解如何在 MongoDB Go 驱动程序中使用聚合操作。
聚合操作根据聚合管道中的规范处理 MongoDB 集合中的数据。聚合管道由一个或多个阶段组成。每个阶段都根据其表达式运算符执行操作。驱动程序执行聚合管道后,会返回聚合结果。
类比
聚合操作的运作方式与汽车工厂类似。汽车工厂内有一条装配线。装配线设有配备专门工具来完成特定作业的装配站。要制造汽车,需要将毛坯零件送到工厂。然后,装配线将零件改造并组装成汽车。
装配线类似于聚合管道,装配线上的装配站类似于聚合阶段,专用工具代表表达式运算符,而成品则类似于聚合结果。
比较操作
下表列出了通过使用查找和聚合操作来执行的任务。
查找操作 | 聚合操作 |
---|---|
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 |
限制
聚合操作有局限性。执行聚合操作时,注意以下几点:
返回的文档不得违反 BSON 文档大小限制(16 兆字节)。
默认情况下,管道阶段的内存限制为 100 MB。如果需要,可使用 allowDiskUse 方法超过此限制。
$graphLookup阶段有100 MB 的严格内存限制,并忽略
allowDiskUse
。
示例
本部分的示例使用以下 Tea
结构作为 tea
集合中文档的模型:
type Tea struct { Type string Category string Toppings []string Price float32 }
要运行本部分中的示例,请通过使用以下代码段将示例数据加载到 db
数据库中的 tea
集合中:
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)
每个文档都包含有关茶类型、可用配料和价格的信息。
平均评级
以下示例计算并显示每个茶叶类别的平均评分和评分数量。
聚合管道使用 $group
阶段按 category
字段对文档进行分组,使用 $avg
表达式操作符计算平均值,并使用 $sum
表达式操作符计算文档数量。
// 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"]) }
在结果中省略字段
以下示例会匹配可使用牛奶泡沫作为配料的文档,并列出两种最便宜的选项。
聚合管道包含以下阶段:
$match
与toppings
字段包含“牛奶泡沫(milk foam)”的文档进行匹配的阶段$unset
阶段,用于省略_id
和category
字段$sort
阶段按升序排序对price
和toppings
进行排序$limit
阶段以显示前两个文档
// 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) }
更多信息
要了解有关所提及术语的更多信息,请参阅以下指南:
要查看更多聚合示例,请参阅以下指南:
要了解有关 Aggregate()
方法及其行为的更多信息,请参阅检索数据。
API 文档
要进一步了解本指南所讨论的任何方法或类型,请参阅以下 API 文档: