I am trying to switch an API implementation I have been working on from GORM ORM library to SQLx to make data access more efficient. In particular, I am trying to get rid of some SELECT N+1 problems. So, I have a one to many relationship where a site has posts. The API I am implementing returns a list of sites as a JSON object and each site has a nested posts list. The structure looks somewhat like this
{
"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 ...
]
}
This was easy to implement in GORM, but once I looked at the SQL GORM was running to implement this, I realized that it was doing a SELECT from posts for every site in the list. So I am trying to use SQL like this to avoid the N+1 problem.
SELECT s.id, s.name, p.title, p.published FROM sites as s, posts as p WHERE p.site_id = s.id
This gets me all the data I need in a single query. But I am somewhat stuck on how to scan all of this into a list of site structs. In GORM, I had following structs defined (simplified for brevity)
type struct Post {
Id uint `json:"-"`
Title string
Published time.Time
SiteId uint `json:"-"`
Site Site `json:"-"`
}
type struct Site {
Id uint
Name string
}
And then I would do something like
var sites []Site
result := db.Preload('Posts').Find(&sites)
if result.Error != nil {
... error handling ...
} else {
operate on sites here
}
So the question is, how do I scan my new SQL using SQLx into a slice of structs in a way that results in a similar data structure that GORM produced? I don't mind writing my own scanner, but I still want to be able to use SQLx Select() and Get() methods. What do I need to do to make this work?
var sites []Site err := db.Select(query, &sites) // where query is SQL from above
Edit: it seems that if I do the exact code I present in this question, GORM doesn't actually do N+1 selects, it runs two queries, one simple SELECT for sites and one SELECT ... WHERE ... IN ... for posts and then collates the two result sets. I still want to know how to do this in SQLx though.