mgo 作为 mongodb 的 go 驱动,不提供 orm 式的自动关联加载;推荐使用 id 引用 + 显式查询模式:结构体中仅存储 []bson.objectid,再通过封装方法按需查库填充关联数据。
在 MongoDB 这类文档数据库中,“关系”并非通过外键强制约束,而是由应用层设计决定——是嵌入(Embedding)还是引用(Referencing)。mgo 本身是一个轻量级驱动,不内置关
系映射、懒加载或 JOIN 功能,因此需开发者主动建模。
将 Friends 字段定义为 []bson.ObjectId(小写字段以避免导出),并提供一个显式的 Friends() 方法来获取完整用户数据:
type User struct {
Id bson.ObjectId `json:"_id,omitempty" bson:"_id,omitempty"`
Username string `json:"username" bson:"username"`
Email string `json:"email" bson:"email"`
Password string `json:"password" bson:"password"`
friends []bson.ObjectId `json:"-" bson:"friends"` // 小写 + json:"-"`
}
// Friends 返回当前用户的所有好友完整对象(按需查询)
func (u *User) Friends(session *mgo.Session) ([]User, error) {
if len(u.friends) == 0 {
return []User{}, nil
}
var users []User
err := session.DB("yourdb").C("users").Find(bson.M{
"_id": bson.M{"$in": u.friends},
}).All(&users)
return users, err
}? 使用示例:user := &User{Id: userId, friends: []bson.ObjectId{friendId1, friendId2}} friends, err := user.Friends(session) if err != nil { /* handle */ } // friends 现在是完整的 []User 切片
type UserID bson.ObjectId
type User struct {
// ...
Friends []UserID `json:"friends" bson:"friends"`
}mgo 不隐藏数据库语义,这恰是其优势:透明、可控、无魔法。所谓“关系”,本质是应用逻辑对 ID 引用的解释与协作。坚持「存储 ID、按需查库」的设计,既符合 MongoDB 的文档模型哲学,也便于后期扩展(如引入缓存、服务拆分或切换为图数据库)。真正的“关系管理”,不在驱动里,而在你的业务方法中。