Golang操作MongoDB:含datetime的游标反序列化失败的解决办法
问题解决方法
核心原因
错误本质是聚合查询返回的JoinDate字段为MongoDB的UTC datetime类型,但你用来接收结果的结构体中,该字段类型与返回类型不匹配(大概率是误写成了string),或者聚合分组时错误地将JoinDate转成了字符串,导致解码失败。
具体修复步骤
1. 定义正确的聚合结果接收结构体
确保结构体中JoinDate类型为time.Time,且bson标签与聚合管道里的键名严格一致:
type DuplicateGroup struct { AccountId string `bson:"accountId"` SessionId string `bson:"sessionId"` Template string `bson:"template"` JoinDate time.Time `bson:"joinDate"` IDs []primitive.ObjectID `bson:"ids"` // 存储同组内的所有文档ID Count int `bson:"count"` }
2. 修正聚合管道逻辑
分组阶段直接使用原JoinDate字段作为分组键,不要用$toString等操作将其转为字符串,保证返回的字段类型为datetime:
pipeline := mongo.Pipeline{ { {"$group", bson.D{ {"_id", bson.D{ {"accountId", "$accountId"}, {"sessionId", "$sessionId"}, {"template", "$template"}, {"joinDate", "$joinDate"}, // 直接使用原datetime字段分组 }}, {"ids", bson.D{{"$push", "$_id"}}}, {"count", bson.D{{"$sum", 1}}}, }}, }, { {"$match", bson.D{{"count", bson.D{{"$gt", 1}}}}}, // 只筛选出重复的分组 }, }
3. 正确解码聚合结果
用上面定义的DuplicateGroup结构体接收查询结果,此时time.Time类型可以正常解码MongoDB的datetime:
cur, err := ms.Collection("accounts").Aggregate(ms.GetContext(), pipeline) if err != nil { // 处理聚合错误 return err } defer cur.Close(ms.GetContext()) var duplicateGroups []DuplicateGroup if err := cur.All(ms.GetContext(), &duplicateGroups); err != nil { // 处理解码错误 return err } // 遍历分组删除重复数据:保留每组第一个文档,删除其余 for _, group := range duplicateGroups { for i := 1; i < len(group.IDs); i++ { _, err := ms.Collection("accounts").DeleteOne(ms.GetContext(), bson.D{{"_id", group.IDs[i]}}) if err != nil { // 处理删除错误 continue } } }
额外检查点
- 确认原
Account结构体中JoinDate的bson标签正确(如果原集合中字段名是joinDate,标签要对应) - 聚合管道中所有涉及
JoinDate的操作,都不要修改其类型,保持datetime格式
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

