英文:
Using LEFT JOIN on Golang and mapping to a struct
问题
我在Go语言中有以下结构体:
type Struct1 struct {
ID int64 `db:"id"`
InternalID int64 `db:"internal_id"`
Structs2 []Struct2
}
type Struct2 struct {
ID int64 `db:"id"`
InternalID int64 `db:"internal_id"`
SomeText string `db:"some_text"`
}
这两个结构体之间的关系是:一个Struct1只能连接到N个Struct2,通过internal_id进行连接。所以我正在执行以下查询:
SELECT *
FROM struct1 st1
LEFT JOIN struct2 st2
ON
st1.internal_id = st2.internal_id
LIMIT 10
OFFSET (1 - 1) * 10;
在Go中执行这个查询后,我想知道是否可以通过正确映射Struct2数组来创建一个Struct1数组。如果可能的话,我该如何做?提前感谢。
我正在使用Postgres和sqlx。
英文:
I have the following structs on Go:
type Struct1 struct {
ID int64 `db:id`
InternalID int64 `db:internal_id`
Structs2 []Struct2
}
type Struct2 struct {
ID int64 `db:id`
InternalID int64 `db:internal_id`
SomeText string `db:some_text`
}
The relation between this two is: There only can be one Struct1, connect to N Struct2 by the internal_id. So I am doing this query:
SELECT*
FROM struct1 st1
LEFT JOIN struct2 st2
ON
st1.internal_id = st2.internal_id
LIMIT 10
OFFSET (1 - 1) * 10;
By executing this query on Go, I wanna know if i can: Create an array of Struct1, by mapping correctly the array Struct2 on it. If it is possible, how can I do it? Thanks in advance.
I'm using Postgres and sqlx.
答案1
得分: 1
这完全取决于你使用的连接数据库的库/客户端,然而,我从未见过有库支持你尝试做的事情,所以我将提供一个自定义实现供你参考。完全透明地说,我没有测试过这个代码,但希望它能给你一个大致的思路,任何人都可以随意进行修改。
package main
type Struct1 struct {
ID int64 `db:id`
InternalID int64 `db:internal_id`
Structs2 []Struct2
}
type Struct2 struct {
ID int64 `db:id`
InternalID int64 `db:internal_id`
SomeText string `db:some_text`
}
type Row struct {
Struct1
Struct2
}
func main() {
var rows []*Row
// 使用你所使用的 SQL 客户端将响应解码到 rows 变量中
// 我们将把 struct1 分组到一个 map 中,然后遍历所有的行,从已经添加到 map 中的行中取出 struct2 的内容,
// 然后将 struct2 追加到它们上面。这样就有效地将 rows 转换为 struct1 和 struct2 之间的一对多关系。
mapped := map[int64]*Struct1{}
for _, r := range rows {
// map 的键将是 struct1 的内部 ID(这是一对多关系中的“一”)
if _, ok := mapped[r.Struct1.InternalID]; !ok {
// 如果这是具有 struct1 的内部 ID 的第一行,请确保初始化键。
mapped[r.Struct1.InternalID] = &r.Struct1
}
// 将 struct2(一对多关系中的“多”)追加到 struct1 的 struct2 数组中。
mapped[r.Struct1.InternalID].Structs2 = append(mapped[r.Struct1.InternalID].Structs2, r.Struct2)
}
// 如果需要,将其转换为切片
results := make([]*Struct1, len(mapped))
i := 0
for _, v := range mapped {
results[i] = v
i++
}
}
希望对你有所帮助!
英文:
This is entirely dependent on the library/client you're using to connect to the database, however, I have never seen a library support what you're trying to do so I'll provide a custom implementation that you can do. Full disclosure, I did not test this but I hope it gives you the general idea and anyone should feel free to add edits.
package main
type Struct1 struct {
ID int64 `db:id`
InternalID int64 `db:internal_id`
Structs2 []Struct2
}
type Struct2 struct {
ID int64 `db:id`
InternalID int64 `db:internal_id`
SomeText string `db:some_text`
}
type Row struct {
Struct1
Struct2
}
func main() {
var rows []*Row
// decode the response into the rows variable using whatever SQL client you use
// We'll group the struct1s into a map, then iterate over all the rows, taking the
// struct2 contents off of rows we've already added to the map and then appending
// the struct2 to them. This effectively turns rows into one-to-many relationships
// between struct1 and struct2.
mapped := map[int64]*Struct1{}
for _, r := range rows {
// The key of the map is going to be the internal ID of struct1 (that's the ONE
// in the one-to-many relationship)
if _, ok := mapped[r.Struct1.InternalID]; ok {
// Make sure to initialize the key if this is the first row with struct1's
// internal ID.
mapped[r.Struct1.InternalID] = &r.Struct1
}
// Append the struct 2 (the MANY in the one-to-many relationship) to the struct1s
// array of struct2s.
mapped[r.Struct1.InternalID].Structs2 = append(mapped[r.Struct1.InternalID].Structs2, r.Struct2)
}
// Then convert it to a slice if needed
results := make([]*Struct1, len(mapped))
i := 0
for _, v := range mapped {
results[i] = v
i++
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论