2

我正在尝试将我一直在研究的 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 中执行此操作。

4

1 回答 1

0

这可能不是一个答案,但评论太长了。

如果您仍在使用 GORM,您可以创建自定义 SQL。查看文档:http: //jinzhu.me/gorm/advanced.html#sql-builder

对你来说,它可能是这样的:

// Scan

type struct Post {
    Id        uint      `json:"-"`
    Title     string
    SiteId    uint      `json:"-"`
    Site      Site      `json:"-"`
}

var result Post

db.Raw("
SELECT s.id, s.name, p.title, p.published 
FROM sites as s, posts as p 
WHERE p.site_id = s.id").Scan(&result)
于 2017-09-28T13:49:13.003 回答