
本文详解如何将 MongoDB 原生聚合管道(含 $match、$project 中嵌套 $cond 与 $or)准确转换为 Go 语言中基于 mgo 驱动的可执行代码,并提供结构清晰、可直接运行的示例。
本文详解如何将 mongodb 原生聚合管道(含 `$match`、`$project` 中嵌套 `$cond` 与 `$or`)准确转换为 go 语言中基于 mgo 驱动的可执行代码,并提供结构清晰、可直接运行的示例。
在 Go 中使用 mgo 驱动执行 MongoDB 聚合操作,关键在于将每个聚合阶段(stage)构造成 bson.M 类型的 map,并按顺序传入 Pipe() 方法。尤其需注意:$cond 是三元表达式,其语法为 [$condition, $trueCase, $falseCase],必须以 slice 形式传入;而 $or 和 $eq 等操作符也需严格遵循 BSON 结构嵌套规则。
以下为完整可运行的 Go 代码示例(假设已建立有效 *mgo.Session):
collection := session.DB("dbName").C("devices")
// Stage 1: $match
stageMatch := bson.M{
"$match": bson.M{
"userId": "v73TuQqZykbxFXsWo",
"state": true,
},
}
// Stage 2: $project — 注意 $cond 的写法:[]interface{}{condition, trueValue, falseValue}
conditionWeight := []interface{}{
bson.M{
"$or": []bson.M{
{ "$eq": []string{"$categorySlug", "air_fryer"} },
{ "$eq": []string{"$categorySlug", "iron"} },
},
},
0, // true case: weight = 0
1, // false case: weight = 1
}
stageProject := bson.M{
"$project": bson.M{
"userId": 1,
"categorySlug": 1,
"weight": conditionWeight,
},
}
// Stage 3: $sort
stageSort := bson.M{
"$sort": bson.M{"weight": 1},
}
// Stage 4: $limit
stageLimit := bson.M{
"$limit": 10,
}
// 执行聚合管道
pipe := collection.Pipe([]bson.M{stageMatch, stageProject, stageSort, stageLimit})
// 获取结果(示例:遍历并打印)
var results []bson.M
err := pipe.All(&results)
if err != nil {
log.Fatal("聚合执行失败:", err)
}
for _, doc := range results {
fmt.Printf("ID: %v, Category: %v, Weight: %v\n",
doc["userId"], doc["categorySlug"], doc["weight"])
}⚠️ 重要注意事项:
-
mgo.v2已归档且不再维护(官方推荐迁移到 mongo-go-driver),生产环境应尽快升级; -
$eq中字段引用必须加$前缀(如"$categorySlug"),否则会被视为字面量字符串; -
[]string{"$categorySlug", "air_fryer"}顺序不可颠倒:$eq要求[field, value]; - 若需支持动态 userId 或 category 列表,建议将硬编码值替换为变量,并用
fmt.Sprintf或bson.M动态构造条件; -
Pipe()返回的*mgo.Pipe支持链式调用(如.All()、.One()、.Iter()),但不支持.Count()— 如需统计,需额外使用$group阶段。
该模式可灵活扩展:添加 $lookup 关联、$addFields 计算新字段或 $facet 多维度分析,均只需按相同方式构造对应 bson.M 阶段并追加至管道切片即可。



















