我正在尝试将我一直在使用的API实现从GORM ORM库切换到SQLx,以提高数据访问效率 . 特别是,我试图摆脱一些SELECT N 1问题 . 所以,我有一对多关系网站有帖子 . 我正在实现的API返回一个站点列表作为JSON对象,每个站点都有一个嵌套的 posts
列表 . 结构看起来有点像这样
{
"sites": [
{
"id": 1,
"name": "Site #1",
"posts" [
{"title": "Post #1", "published": "1/2/2000", ... },
{"title": "Post #2", "published": "1/3/2000", ... },
... more posts ...
]
},
{
"id": 2,
"name": "Site #2",
"posts": [
... post list for site #2 ...
]
}
... more sites ...
]
}
这很容易在GORM中实现,但是一旦我看到SQL GORM正在运行来实现它,我意识到它正在为列表中的每个站点的帖子做一个SELECT . 所以我试图像这样使用SQL来避免N 1问题 .
SELECT s.id, s.name, p.title, p.published
FROM sites as s, posts as p
WHERE p.site_id = s.id
这可以在单个查询中获取我需要的所有数据 . 但我有点坚持如何将所有这些扫描到网站结构列表中 . 在GORM中,我定义了以下结构(简化为简洁)
type struct Post {
Id uint `json:"-"`
Title string
Published time.Time
SiteId uint `json:"-"`
Site Site `json:"-"`
}
type struct Site {
Id uint
Name string
}
然后我会做类似的事情
var sites []Site
result := db.Preload('Posts').Find(&sites)
if result.Error != nil {
... error handling ...
} else {
operate on sites here
}
所以问题是,如何使用SQLx将我的新SQL扫描到一个结构片中,从而产生与GORM生成的类似数据结构?我不介意编写自己的扫描仪,但我仍然希望能够使用SQLx Select()
和 Get()
方法 . 我需要做些什么来完成这项工作?
var sites []Site
err := db.Select(query, &sites) // where query is SQL from above
Edit: 似乎如果我在这个问题中做了确切的代码,GORM实际上并没有做N 1选择,它运行两个查询,一个简单的SELECT用于站点,一个SELECT ... WHERE ... IN ...对于帖子,然后整理两个结果集 . 我仍然想知道如何在SQLx中执行此操作 .
1 回答
这可能不是一个答案,但对于评论来说太长了 .
如果您仍在使用GORM,则可以创建自定义SQL . 见文档:http://jinzhu.me/gorm/advanced.html#sql-builder
对你来说它可能是这样的: