Gorm eager loading 加入多个关系

标签 go join eager-loading go-gorm

我有这样的数据设计:交易属于授权,而授权又属于客户。或者用结构体表示:

type Transaction struct { 
    shared.Transaction // transaction data
    MandateID   string
    Mandate     *Mandate
}

type Mandate struct {
    shared.Mandate // mandate data
    ClientID      string
    Client        *Client
    Transactions  []Transaction
}

type Client struct {
    shared.Client // client data
    Mandates   []Mandate

}

我一直在尝试使用 joins preloading 预加载交易及其授权和客户数据。 .需要注意的是,此预加载仅适用于“拥有一个”或“属于”类型的关系。

如果我只需要交易和授权数据,这会很好地工作:

var trx []rdb.Transaction
err = t.db.
    Joins("Mandate").
    Find(&trx, "batch_id = ?", batchID).Error

但是,一旦我尝试同时加载客户端,gorm 就会生成无效的 SQL。代码:

var trx []rdb.Transaction
err = t.db.
    Joins("Mandate").
    Joins("Mandate.Client").
    Find(&trx, "batch_id = ?", batchID).Error

我以前使用普通预加载,但是 Preload 启动的多个查询开始成为一个严重的性能问题。用 SQL 编写整个查询并扫描结果也是一种选择,但这首先违背了使用 ORM 的目的。

我如何使用 gorm 在单个查询中获取交易及其授权和客户数据?

最佳答案

要加载嵌套关联,例如 Mandate.Client,您需要使用 Preload 函数。

var trx []rdb.Transaction
err = t.db.
    Preload("Mandate.Client").
    Find(&trx, "batch_id = ?", batchID).Error

关于性能问题,是的,Preload 函数确实执行了多个查询。但是,如果您查看查询,您会发现它们已经尽可能地进行了优化。查询应如下所示:

SELECT * FROM clients WHERE id IN (23,43,12,3,2,73,121,1,9,21,39);

SELECT * FROM mandates WHERE id IN (1,2,3,4,5,6,21,43,54);

它确实扫描了整个表,但您可以看到它试图加载一组非常具体的数据。我不认为这个 ORM 能提供比这更多的帮助。事实是,如果您的批处理中有很多交易,并且您希望立即加载所有详细信息,那么您的性能会受到一些影响。

要提高您的方法的性能,您始终可以尝试通过使用 OffsetLimit 函数来引入分页以限制返回的事务数。或者,使用原始 SQL 查询返回非规范化结果并使用 for 循环和 Scan 读取行。

关于Gorm eager loading 加入多个关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71170220/

相关文章:

golang 运行时错误 : index out of range

selenium - Go - 我如何安装selenium以在go语言中使用它?

mysql - 在 A 行上左连接多个 B 行时如何对 A 行列求和

sql - 从多个表中获取记录

php - 我可以在 Laravel 中急切/延迟加载属性吗?

go - 如何模拟客户端和服务器之间的完全网络丢失?

mysql - 从一个表中加入计数以从另一个表中选择 - mysql

php - Laravel 4 急切加载 - 所有关系都被推到第一个返回的对象

mysql - 在 Rails 3 中急切加载?

go - 为什么我的 Users/myname/go 文件夹不存在?