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