如何将指定SQL查询转换为Go语言中的MongoDB聚合查询
MySQL转MongoDB聚合查询解决方案
原SQL逻辑拆解
原SQL核心逻辑:
- 筛选
clientid = 12的记录 - 按
presenceid分组 - 对每组计算:将
datefinished(为空则用当前时间)与dateadded的时间差转成秒数,再求和
MongoDB聚合管道实现
对应的MongoDB聚合管道包含两个核心阶段:
db.userpresences.aggregate([ { $match: { clientid: 12 } }, { $group: { _id: "$presenceid", count: { $sum: { $divide: [ { $subtract: [ { $ifNull: ["$datefinished", "$$NOW"] }, "$dateadded" ] }, 1000 ] } } } } ])
逻辑对应说明:
$ifNull: ["$datefinished", "$$NOW"]:等价于SQL的IFNULL(userpresences.datefinished, NOW()),$$NOW是MongoDB聚合内置的当前时间变量$subtract:替代SQL的TIMEDIFF,MongoDB中日期直接相减会得到毫秒级差值$divide: [..., 1000]:将毫秒差值转换为秒数,对应SQL的TIME_TO_SEC$sum:对每组的秒数差值求和,和SQL的SUM()功能完全一致
对应的Go代码实现
补充过滤阶段并修正分组计算逻辑,完整代码如下:
import ( "context" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/bson" ) func calculatePresenceDuration(collection *mongo.Collection, ctx context.Context) (*mongo.Cursor, error) { // 过滤阶段:对应SQL的WHERE clientid = 12 matchStage := bson.D{{"$match", bson.D{{"clientid", 12}}}} // 分组计算阶段:实现SUM(...)的统计逻辑 groupStage := bson.D{ {"$group", bson.D{ {"_id", "$presenceid"}, {"count", bson.M{ "$sum": bson.M{ "$divide": []interface{}{ bson.M{ "$subtract": []interface{}{ bson.M{"$ifNull": []interface{}{"$datefinished", "$$NOW"}}, "$dateadded", }, }, 1000, }, }, }}, }}, } // 执行聚合查询 return collection.Aggregate(ctx, mongo.Pipeline{matchStage, groupStage}) }
代码说明:
- 先通过
$match过滤数据,减少分组计算的数据量,和SQL的WHERE作用一致 $$NOW在Go的BSON结构中直接以字符串传入,MongoDB会自动识别为内置变量- 用
bson.M和bson.D嵌套构建聚合表达式,保证结构符合MongoDB的语法要求
内容的提问来源于stack exchange,提问作者Marko Mikulić
相关产品推荐
相关产品推荐

