如何在自引用多对多关系中高效获取用户关注列表?
解决方案
要高效获取用户关注的列表,核心是补充反向关联关系或直接通过JOIN查询实现,两种方式都能避免N+1查询的性能问题:
方法1:补充模型关联定义(推荐)
当前你的模型只定义了「粉丝(Followers)」的关联,缺少「关注的人(Following)」的反向关联。需要在User结构体中添加Following字段,并通过GORM标签明确关联表、外键和引用键的对应关系:
type User struct { gorm.Model Username string Password string // Followers:关注当前用户的粉丝列表 // 关联表:user_followers(如果实际生成的是user_friends,替换为对应表名) // 外键规则:当前用户ID对应关联表的user_id,粉丝ID对应关联表的follower_id Followers []*User `gorm:"many2many:user_followers;foreignKey:ID;joinForeignKey:user_id;References:ID;joinReferences:follower_id"` // Following:当前用户关注的列表 // 反向关联规则:当前用户ID对应关联表的follower_id,被关注用户ID对应关联表的user_id Following []*User `gorm:"many2many:user_followers;foreignKey:ID;joinForeignKey:follower_id;References:ID;joinReferences:user_id"` }
注意:如果你的关联表实际名称是
user_friends(你提到迁移后生成的是这个表),请把标签中的many2many:user_followers替换为many2many:user_friends,确保与数据库实际表名一致。
添加完成后,就可以像获取粉丝列表一样,用GORM的Association方法高效获取关注列表:
var following []User // user为当前查询的用户实例 db.Model(&user).Association("Following").Find(&following)
GORM会自动生成JOIN语句,一次性查询出所有关注的用户,彻底避免N+1性能问题。
方法2:直接使用JOIN查询(无需修改模型)
如果不想修改现有模型,可以通过GORM的Joins方法直接构造JOIN查询,同样能高效获取数据:
var following []User // 替换user_followers为实际关联表名(如user_friends) db.Joins("JOIN user_followers ON user_followers.user_id = users.id"). Where("user_followers.follower_id = ?", user.ID). Find(&following)
这条语句直接关联用户表和关联表,通过follower_id = 当前用户ID筛选出所有被关注的用户,一次性完成查询,性能最优。
原理说明
你的原模型中,Followers字段的关联逻辑是:关联表中user_id指向当前用户,follower_id指向关注当前用户的人(粉丝)。而要获取当前用户关注的人,需要反向匹配:关联表中follower_id指向当前用户,user_id指向被关注的用户。补充Following字段就是明确这个反向关联关系,让GORM能正确生成查询语句。
内容的提问来源于stack exchange,提问作者camelCaseIsGoodPractice

