我正在尝试将我一直在研究的 API 实现从 GORM ORM 库切换到 SQLx,以提高数据访问效率。特别是,我试图摆脱一些 SELECT N+1 问题。所以,我有一个网站有帖子的一对多关系。我正在实现的 API 将站点列表作为 JSON 对象返回,并且每个站点都有一个嵌套posts列表。结构看起来有点像这样
{
“网站”:[
{
“身份证”:1,
"name": "站点 #1",
“帖子” [
{"title": "Post #1", "published": "1/2/2000", ... },
{"title": "Post #2", "published": "1/3/2000", ... },
...更多帖子...
]
},
{
“身份证”:2,
"name": "站点 #2",
“帖子”:[
... 站点 #2 的帖子列表 ...
]
}
... 更多网站 ...
]
}
这在 GORM 中很容易实现,但是当我查看 GORM 正在运行的 SQL 来实现它时,我意识到它正在对列表中的每个站点的帖子执行 SELECT。所以我试图使用这样的 SQL 来避免 N+1 问题。
选择 s.id、s.name、p.title、p.published FROM 站点为 s,帖子为 p 其中 p.site_id = s.id
这让我在一个查询中获得了我需要的所有数据。但是我有点坚持如何将所有这些扫描到站点结构列表中。在 GORM 中,我定义了以下结构(为简洁起见)
类型结构邮政{
ID uint `json:"-"`
标题字符串
发表时间.Time
SiteId uint `json:"-"`
站点站点`json:“-”`
}
类型结构站点{
标识单位
名称字符串
}
然后我会做类似的事情
var 站点 []站点
结果 := db.Preload('Posts').Find(&sites)
如果结果。错误!= nil {
... 错误处理 ...
} 别的 {
在这里的网站上运营
}
所以问题是,我如何使用 SQLx 将我的新 SQL 扫描到一个结构切片中,从而产生与 GORM 产生的类似数据结构?我不介意编写自己的扫描仪,但我仍然希望能够使用 SQLxSelect()和Get()方法。我需要做什么才能完成这项工作?
var 站点 []站点 err := db.Select(query, &sites) // 其中查询是上面的 SQL
编辑:似乎如果我执行我在这个问题中提出的确切代码,GORM 实际上并没有进行 N+1 选择,它运行两个查询,一个简单的 SELECT 用于站点,一个 SELECT ... WHERE ... IN 。 .. 对于帖子,然后整理两个结果集。不过,我仍然想知道如何在 SQLx 中执行此操作。