gorm 预加载的使用场景

更新日期: 2023-05-22 阅读次数: 13208 字数: 412 分类: golang

背景

我正在用 golang gin 写的一个统计人数小程序后台服务涉及两个大数据表

  • 用户表
  • 活动参与的用户表

在查询一个活动参与的所有用户信息时,需要同时用到这两个表。考虑到运营一段时间之后,这两个表的数据量不可控,所有不打算使用联表查询。而采用

  1. 先查询活动对应的用户 id 集合
  2. 然后 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

tags: gorm

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式