Golang中MongoDB(Mgo)管道操作解析
Golang中MongoDB(Mgo)管道操作解析 大家好
想了解如何访问Mongo集合管道聚合的结果。根据我在网上看到的所有示例或博客,结果是[]bson.M{}类型。在记录日志时,我看到结果是一个映射数组/切片,其中还包含嵌套的映射。该如何提取它?我没有看到任何关于访问结果的示例,比如将结果值映射回某个结构体。
提前感谢。
4 回复
问题在于如何访问 bson.m{} 数组的字段,在这种情况下它应该是一个映射。
更多关于Golang中MongoDB(Mgo)管道操作解析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
测试查询
type message struct {
ID int64 `bson:"_id"`
Size int64 `bson:"size"`
}
func (e *ets) get(ctx context.Context, clientID int64) (int64, error) {
sess := e.mgoSess.Copy()
defer sess.Close()
var result []*message
pipeline := []bson.M{
{
"$match": bson.M{
"id": ID,
},
},
{
"$group": bson.M{
"_id": "null",
"size": bson.M{"$sum": "$size"},
},
},
{
"$project": bson.M{
"size": 1,
},
},
}
err := sess.
DB("").
C(collection).
Pipe(pipeline).All(ctx, &result)
if err != nil {
err = errors.New("MongoDB find aggregation")
return 0, err
}
if len(result) == 0 {
return 0, nil
}
return result[0].Size, nil
}
在Go语言中使用mgo库进行MongoDB管道聚合时,聚合结果通常以[]bson.M类型返回。要访问这些结果,可以通过遍历切片并解析每个bson.M映射中的字段。如果需要将结果映射到结构体,可以使用bson.Unmarshal或mgo的Iter.All方法结合自定义结构体。
以下是一个完整示例,展示如何执行管道聚合并提取结果:
package main
import (
"fmt"
"log"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// 定义结构体以映射聚合结果
type AggregationResult struct {
ID string `bson:"_id"`
Count int `bson:"count"`
Total int `bson:"total"`
}
func main() {
// 连接到MongoDB
session, err := mgo.Dial("localhost")
if err != nil {
log.Fatal(err)
}
defer session.Close()
collection := session.DB("testdb").C("testcollection")
// 定义管道阶段
pipeline := []bson.M{
{
"$group": bson.M{
"_id": "$category",
"count": bson.M{"$sum": 1},
"total": bson.M{"$sum": "$value"},
},
},
}
// 执行聚合操作
var results []bson.M
err = collection.Pipe(pipeline).All(&results)
if err != nil {
log.Fatal(err)
}
// 方法1:直接访问bson.M结果
fmt.Println("Raw bson.M results:")
for _, result := range results {
id := result["_id"]
count := result["count"]
total := result["total"]
fmt.Printf("ID: %v, Count: %v, Total: %v\n", id, count, total)
}
// 方法2:将结果映射到结构体切片
var structuredResults []AggregationResult
for _, result := range results {
// 将bson.M转换为bson字节
data, err := bson.Marshal(result)
if err != nil {
log.Fatal(err)
}
var structured AggregationResult
err = bson.Unmarshal(data, &structured)
if err != nil {
log.Fatal(err)
}
structuredResults = append(structuredResults, structured)
}
fmt.Println("\nStructured results:")
for _, result := range structuredResults {
fmt.Printf("ID: %s, Count: %d, Total: %d\n", result.ID, result.Count, result.Total)
}
}
在这个示例中:
- 首先执行管道聚合,结果存储在
[]bson.M中。 - 直接访问
bson.M中的字段,使用键名如result["_id"]。 - 通过
bson.Marshal和bson.Unmarshal将每个bson.M映射到自定义结构体AggregationResult。
如果聚合结果字段固定,也可以直接使用结构体切片接收结果:
var structuredResults []AggregationResult
err = collection.Pipe(pipeline).All(&structuredResults)
if err != nil {
log.Fatal(err)
}
这种方式要求结构体字段的bson标签与聚合输出字段完全匹配。

