You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang MGO多参数分组并按datetime获取最新记录

用Golang + mgo实现分组取最新测试记录

嘿,这个需求我之前做项目时刚好碰到过,用MongoDB的聚合框架搭配mgo就能完美解决!下面给你捋清楚思路和具体代码:

核心思路

我们需要通过聚合管道分三步搞定:

  1. 分组取最新时间:按serial number、stage、stage order这三个字段分组,把每组里最大的datetime(也就是最新完成的记录时间)捞出来
  2. 关联原集合拿完整记录:把第一步的分组结果和原测试记录集合关联,匹配出对应那个最新时间的完整记录
  3. 整理输出字段:去掉聚合过程中生成的冗余数据,只保留你需要的字段

具体代码实现

先假设你的测试记录结构体是这样的(根据实际字段调整就行):

import (
    "fmt"
    "time"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
)

type TestRecord struct {
    SerialNumber string    `bson:"serial number"`
    Stage        string    `bson:"stage"`
    StageOrder   int       `bson:"stage order"`
    Datetime     time.Time `bson:"datetime"`
    // 这里加你实际的其他字段,比如测试结果、备注之类的
    Result string `bson:"result"`
}

然后是执行聚合查询的核心代码:

// 先建立MongoDB连接
session, err := mgo.Dial("mongodb://localhost:27017")
if err != nil {
    panic(fmt.Errorf("连接MongoDB失败: %v", err))
}
defer session.Close()

// 指定你的数据库和集合
coll := session.DB("your_test_db").C("test_records")

// 构建聚合管道
pipeline := []bson.M{
    // 第一步:分组,获取每组的最新datetime
    {
        "$group": bson.M{
            "_id": bson.M{
                "serialNumber": "$serial number",
                "stage":        "$stage",
                "stageOrder":   "$stage order",
            },
            "latestDatetime": bson.M{"$max": "$datetime"},
        },
    },
    // 第二步:关联原集合,多字段匹配找到对应最新记录
    // 这里用let+子管道的方式,因为要匹配多个字段的组合
    {
        "$lookup": bson.M{
            "from": "test_records",
            "let": bson.M{
                "sn":         "$_id.serialNumber",
                "stage":      "$_id.stage",
                "stageOrder": "$_id.stageOrder",
                "latestDt":   "$latestDatetime",
            },
            "pipeline": []bson.M{
                {
                    "$match": bson.M{
                        "$expr": bson.M{
                            "$and": []bson.M{
                                {"$eq": ["$serial number", "$$sn"]},
                                {"$eq": ["$stage", "$$stage"]},
                                {"$eq": ["$stage order", "$$stageOrder"]},
                                {"$eq": ["$datetime", "$$latestDt"]},
                            },
                        },
                    },
                },
            },
            "as": "latestRecord",
        },
    },
    // 展开关联后的数组(每组只会匹配到一条记录,所以放心unwind)
    {"$unwind": "$latestRecord"},
    // 第三步:投影出需要的字段,去掉中间生成的_id等冗余数据
    {
        "$project": bson.M{
            "_id":           0,
            "serial number": "$latestRecord.serial number",
            "stage":         "$latestRecord.stage",
            "stage order":   "$latestRecord.stage order",
            "datetime":      "$latestRecord.datetime",
            "result":        "$latestRecord.result", // 换成你实际需要的其他字段
        },
    },
}

// 执行聚合查询,把结果映射到TestRecord切片里
var latestRecords []TestRecord
if err := coll.Pipe(pipeline).All(&latestRecords); err != nil {
    panic(fmt.Errorf("执行聚合查询失败: %v", err))
}

// 遍历结果看看
for _, record := range latestRecords {
    fmt.Printf("序列号: %s, 阶段: %s, 最新测试时间: %v, 结果: %s\n", 
        record.SerialNumber, record.Stage, record.Datetime, record.Result)
}

小提醒

  • 如果你的datetime字段存的是字符串而不是MongoDB的Date类型,记得先转成Date类型再用$max,不然字符串比较会出问题(比如格式不统一时会出错)
  • 聚合管道里的from字段要和你的集合名称完全一致,MongoDB是大小写敏感的哦
  • 就算每组本来就只有一条记录,这个查询也能正常返回,完全兼容你的场景

内容的提问来源于stack exchange,提问作者xXPhenom22Xx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:01:09