Golang中MongoDB指定用户最近5条评分的中位数计算问题
解决Golang中MongoDB计算用户最近5条反馈rating中位数的问题
一、修正现有聚合阶段的错误
你现有代码里的两处问题确实存在,修正后的基础聚合阶段代码如下:
// 匹配指定user_id的记录,替换原错误的_id匹配条件 matchStage := bson.D{{"$match", bson.D{{"user_id", userID}}}} // 按received_at降序排序,获取最近的记录,替换原错误的created_at字段 sortStage := bson.D{{"$sort", bson.D{{"received_at", -1}}}} // 限制取最近5条记录 limitStage := bson.D{{"$limit", 5}}
二、补充中位数计算的完整聚合逻辑
MongoDB聚合框架可以通过以下步骤实现中位数计算,完整代码如下:
// 1. 匹配目标用户的反馈记录 matchStage := bson.D{{"$match", bson.D{{"user_id", userID}}}} // 2. 按接收时间降序排序,取最近5条 sortStage := bson.D{{"$sort", bson.D{{"received_at", -1}}}} limitStage := bson.D{{"$limit", 5}} // 3. 收集rating到数组,并统计记录数量 groupStage := bson.D{ {"$group", bson.D{ {"_id", "$user_id"}, {"ratings", bson.D{{"$push", "$rating"}}}, {"count", bson.D{{"$sum", 1}}}, }}, } // 4. 根据记录数奇偶性计算中位数 projectStage := bson.D{ {"$project", bson.D{ {"user_id", "$_id"}, {"_id", 0}, {"median", bson.D{ {"$cond", bson.A{ // 判断记录数是否为偶数 {"$even", "$count"}, // 偶数情况:取中间两个数的平均值 {"$avg", bson.A{ {"$arrayElemAt", bson.A{"$ratings", {"$subtract", bson.A{{"$divide", bson.A{"$count", 2}}}, 1}}}, {"$arrayElemAt", bson.A{"$ratings", {"$divide", bson.A{"$count", 2}}}}, }}, // 奇数情况:取数组中间位置的元素 {"$arrayElemAt", bson.A{"$ratings", {"$floor", bson.D{{"$divide", bson.A{"$count", 2}}}}}}, }}, }}, }}, } // 执行聚合查询 cursor, err := r.c.Aggregate(ctx, mongo.Pipeline{matchStage, sortStage, limitStage, groupStage, projectStage}) if err != nil { return 0.0, err } defer cursor.Close(ctx) // 解析聚合结果 var medianResult struct { UserID string `bson:"user_id"` Median float64 `bson:"median"` } if cursor.Next(ctx) { if err := cursor.Decode(&medianResult); err != nil { return 0.0, err } } return medianResult.Median, nil
三、关键说明
- 排序使用
-1(降序)可直接获取最近的5条记录,比升序后取最后5条更高效 - 中位数计算兼容记录数不足5条的场景,逻辑会自动适配实际记录数的奇偶性
- 最终结果会根据记录数返回整数(奇数条)或浮点数(偶数条的平均值)
内容的提问来源于stack exchange,提问作者Neighbourhood
相关产品推荐
相关产品推荐

