gorm 预加载的使用场景

更新日期: 2020-07-11 阅读次数: 358 字数: 385 分类: 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"`
}

参考

  • https://gorm.io/zh_CN/docs/preload.html
  • https://learnku.com/articles/5581/optimizing-laravel-model-queries-with-preload

爱评论不评论

近期节日

2020年08月15日 日本投降日
2020年08月22日 处暑
2020年08月25日 七夕
2020年09月02日 中元节
2020年09月03日 抗日胜利纪念日
2020年09月07日 白露
2020年09月08日 国际扫盲日
2020年09月10日 教师节
2020年09月16日 国际臭氧层保护日
2020年09月16日 世界清洁地球日
2020年09月18日 "九一八"事变纪念日
2020年09月20日 国际爱牙日
查看更多节日