如何使用Go操作MongoDB实现分组查询取组内height最高记录
Go操作MongoDB实现按用户分组取身高最大值记录
基础信息
测试数据集
userId height curry 1 curry 2 kd 3 kd 4 james 2
查询入参
userIds=[curry,kd,james]
期望返回结果
curry 2 kd 4 james 2
需求规则
按userId字段分组,返回每个分组中height字段值最高的对应单条记录,基于Go语言+MongoDB实现。
实现方案
MongoDB端通过聚合管道完成分组计算,核心逻辑分为4个阶段:
$match:提前过滤出入参列表内的用户记录,减少后续聚合计算的数据量$sort:对过滤后的数据按userId升序、height降序排序,保证同一用户下身高最高的记录排在分组最前$group:按userId做分组,通过$first操作符取每个分组排序后的第一条完整记录$replaceRoot:将分组拿到的记录提升为根节点,保证返回结构和普通查询的文档结构一致
代码实现
- 依赖准备:安装官方MongoDB Go驱动
go get go.mongodb.org/mongo-driver/mongo - 定义文档对应的结构体
type UserHeight struct { UserId string `bson:"userId"` Height int `bson:"height"` } - 核心查询逻辑
// 此处提前完成MongoDB连接初始化,col为对应集合的*mongo.Collection实例 ctx := context.Background() // 入参用户ID列表 queryUserIds := []string{"curry", "kd", "james"} // 构造聚合管道 pipeline := mongo.Pipeline{ { {Key: "$match", Value: bson.D{ {Key: "userId", Value: bson.D{{Key: "$in", Value: queryUserIds}}}, }}, }, { {Key: "$sort", Value: bson.D{ {Key: "userId", Value: 1}, {Key: "height", Value: -1}, }}, }, { {Key: "$group", Value: bson.D{ {Key: "_id", Value: "$userId"}, {Key: "record", Value: bson.D{{Key: "$first", Value: "$$ROOT"}}}, }}, }, { {Key: "$replaceRoot", Value: bson.D{{Key: "newRoot", Value: "$record"}}}, }, } // 执行聚合查询 cursor, err := col.Aggregate(ctx, pipeline) if err != nil { log.Fatalf("执行聚合查询失败: %v", err) } defer cursor.Close(ctx) // 解析结果集 var resultList []UserHeight if err = cursor.All(ctx, &resultList); err != nil { log.Fatalf("解析查询结果失败: %v", err) } // 输出验证 for _, item := range resultList { fmt.Printf("%-10s %d\n", item.UserId, item.Height) }
注意事项
- 生产环境建议给
userId字段创建单键索引,能大幅提升匹配、排序阶段的执行效率 - 如果同一用户下存在多条
height同为最大值的记录,上述逻辑会返回排序后排在最前的条目,如果需要固定返回规则,可以在$sort阶段追加排序字段(比如_id降序)保证结果一致性 - 聚合阶段用
$$ROOT获取完整文档的写法兼容性更好,后续集合新增字段时不需要调整聚合逻辑
内容的提问来源于stack exchange,提问作者wuqinqiang
相关产品推荐
相关产品推荐

