背景
我正在用 golang gin 写的一个统计人数小程序后台服务涉及两个大数据表
- 用户表
- 活动参与的用户表
在查询一个活动参与的所有用户信息时,需要同时用到这两个表。考虑到运营一段时间之后,这两个表的数据量不可控,所有不打算使用联表查询。而采用
- 先查询活动对应的用户 id 集合
- 然后 where in ids 来查询对应的用户信息
如果用 golang 手写这个逻辑,还挺啰嗦的。在翻看 gorm 文档时,发现 gorm 支持预加载功能,这个功能类似 laravel eloquent 里的 Eager Loading 功能 (相对于 lazy loading)。
预加载的使用方法
type WxActivityUser struct {
Id int `json:"id"`
......
User UserProfile `json:"user"`
}
type UserProfile struct {
Id int `json:"-"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
}
db.Preload("User").Find(&activityUsers)
如何打印 gorm 语句对应的 SQL
想确认一下,orm 对应的 SQL 是否存在隐患。
db.LogMode(true)
这样就能在 gin 的日志输出中看到每条 sql 语句了。
可以避免联表查询?确实是我想要的效果。
[2020-07-09 21:07:24] [3.37ms] SELECT * FROM `wx_activity_user` WHERE (activity_id = 3) ORDER BY id asc LIMIT 20
[10 rows affected or returned ]
[2020-07-09 21:07:24] [3.26ms] SELECT * FROM `wx_users` WHERE (`id` IN (1))
[1 rows affected or returned ]
can't preload field
[2020-07-09 21:27:19] can't preload field User for models.WxActivityUser
需要在 Preload 的 model 里加上 Id。如果不想在输出为 json 格式时显示 id,只需要加上 json:"-"
type UserProfile struct {
Id int `json:"-"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
}
了解更多
如果要限制 preload 返回的字段,参考 gorm preload 限制 field 字段
参考
- https://gorm.io/zh_CN/docs/preload.html
- https://learnku.com/articles/5581/optimizing-laravel-model-queries-with-preload
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式