Go MongoDB 查询无报错但 Recovery 结构体为空,如何排查?
数据小许
结论
先检查 GetPlayerRecoveryById 查询的集合。写入和更新操作使用 recoveryTableName,读取却使用 playersTableName。如果两个常量指向不同集合,查询可能会在玩家集合中找到 id 相同的文档。若该文档缺少 Recovery 所需的字段,解码后这些字段会保留零值;仅仅缺少字段不会导致解码报错。
将读取集合改为与写入时相同的 recoveryTableName:
func (db *NoSqlConnection[T]) GetPlayerRecoveryById(id T) (recovery.Recovery[T], error) {
filter := bson.M{"id": id}
res := recovery.Recovery[T]{}
err := db.db.
Collection(recoveryTableName).
FindOne(context.TODO(), filter).
Decode(&res)
if err != nil {
return res, err
}
return res, nil
}
为什么没有报错
CreateRecoveryTable 和 AddRecoveryRecord 都操作 recoveryTableName:前者插入 id,后者按 id 更新文档,并设置 game_id 和 record。原查询代码却使用了:
db.db.Collection(playersTableName).FindOne(context.TODO(), filter).Decode(&res)
只要 FindOne 在所选集合中找到符合 id 条件的文档,就会尝试解码。如果 BSON 文档缺少 Recovery[T] 中的 id 或 record 字段,这些字段可能保留零值。因此,没有解码错误并不能说明查询到的就是 recovery 记录。
修复后仍为空时
确认 recoveryTableName 的实际值与写入时完全相同,并检查目标集合中是否存在 id 匹配的文档。还要确认查询传入的 id 与存储值的 BSON 类型一致,例如两边不能一边使用字符串,另一边使用 UUID 或整数。
也可以先将结果解码为 bson.M,查看 MongoDB 实际返回的字段和值,再与 Recovery[T] 的 bson 标签核对:
var doc bson.M
err := db.db.
Collection(recoveryTableName).
FindOne(context.TODO(), bson.M{"id": id}).
Decode(&doc)
if err != nil {
return err
}
fmt.Printf("%#v\n", doc)
如果集合中的 record 是嵌套文档,Record any 可以承载解码结果,但实际 Go 值的类型取决于 BSON 解码方式。如果需要使用具体类型,应将字段声明为对应的结构体类型,并确认它的 bson 标签与文档字段匹配。
备注:内容仅供参考。
