我試圖將我一直在從GORM ORM庫開發的API實現切換到SQLx,以使數據訪問更高效。特別是,我試圖擺脫一些SELECT N + 1問題。所以,我有一個網站有帖子的一對多關係。我正在實現的API將網站列表作爲JSON對象返回,並且每個網站都有一個嵌套的posts
列表。該結構看起來有點像這個優化SQL中的數據訪問
{ "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格姆正在運行來實現這一點,我意識到,這是做一個選擇的職位在每個站點名單。所以我試圖像這樣使用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
編輯:看來,如果我做了確切的代碼我提出的這個問題,GORM實際上並沒有做N + 1個選擇,它運行兩個查詢,一個簡單的選擇網站和一個SELECT ... WHERE ... IN ...發帖,然後整理兩個結果集。我仍然想知道如何在SQLx中做到這一點。
有沒有神奇。只需要首先請求mysql的站點,然後使用簡單的循環提取ID。然後用WHERE ID IN()做第二次請求。最後,使用兩個使用簡單循環的數據集構建新的數據結構。只需使用普通的SQL和SQLx API就可以很好地記錄。 –
我並不期待魔術。我可以編寫一個函數來使用我的單個SQL語句,並創建並填寫Site結構和Post結構。我想我必須寫一個。但我想將其隱藏在行掃描過程中,所以表面上我可以使用本機SQLx API。 –