英文:
Golang sqlx Convert right side of join of many to many into array
问题
我有两个表,Unit和UnitImage,UnitImage有一个外键指向Unit。
我执行了以下SQL查询:
SELECT un.*, array_agg(ROW(ui.is_main, ui.image, ui.id)) AS unit_images
FROM unit un
INNER JOIN unitimage ui ON ui.unit_id = un.id
GROUP BY un.id;
作为响应,我得到了所有Unit字段和连接字段unit_images,格式如下:
{"(f,photos/units/unit_37/90_big.jpg,108)","(f,photos/units/unit_37/91_big.jpg,109)","(f,photos/units/unit_37/92_big.jpg,110)","(f,photos/units/unit_37/93_big.jpg,111)"}
Golang结构体如下:
type Unit struct {
ID *int `json:"id" db:"id"`
Name *string `json:"name" db:"name"`
... 很多其他字段
UnitImages []UnitImages `json:"unit_images" db:"unit_images"`
}
type UnitImages struct {
ID *int `json:"id" db:"id"`
Image *string `json:"image" db:"image"`
IsMain *bool `json:"is_main" db:"is_main"`
}
sqlx代码如下:
query := fmt.Sprintf("SELECT un.*, array_agg(ROW(ui.id, ui.image, ui.is_main)) as unit_images FROM %s un INNER JOIN %s ui ON ui.unit_id = un.id GROUP BY un.id",
unitsTable, unitImagesTable)
err := r.db.Select(&units, query)
我得到了一个错误信息:"sql: Scan error on column index 45, name \"unit_images\": unsupported Scan, storing driver.Value type []uint8 into type *[]*UnitImages"
我是一个Golang的新手,我想知道如何解决这个问题。也许我选择了错误的方法。
我想知道解决这个问题的正确方法。
英文:
I have two tables
Unit and UnitImage with foreign key to Unit.
I do this sql query
SELECT un.*, array_agg(ROW(ui.is_main, ui.image, ui.id)) AS unit_images
FROM unit un
INNER JOIN unitimage ui ON ui.unit_id = un.id
GROUP BY un.id;
In response i got all unit fields and joined field unit_images like this
{"(f,photos/units/unit_37/90_big.jpg,108)","(f,photos/units/unit_37/91_big.jpg,109)","(f,photos/units/unit_37/92_big.jpg,110)","(f,photos/units/unit_37/93_big.jpg,111)"}
Golang Structs
type Unit struct {
ID *int `json:"id" db:"id"`
Name *string `json:"name" db:"name"`
... A lot of fields
UnitImages []UnitImages `json:"unit_images" db:"unit_images"`
}
type UnitImages struct {
ID *int `json:"id" db:"id"`
Image *string `json:"image" db:"image"`
IsMain *bool `json:"is_main" db:"is_main"`
}
sqlx code
query := fmt.Sprintf("SELECT un.*, array_agg(ROW(ui.id, ui.image, ui.is_main)) as unit_images FROM %s un INNER JOIN %s ui ON ui.unit_id = un.id GROUP BY un.id",
unitsTable, unitImagesTable)
err := r.db.Select(&units, query)
I got an error "sql: Scan error on column index 45, name \"unit_images\": unsupported Scan, storing driver.Value type []uint8 into type *[]*UnitImages"
I'm a newbie in golang, i'd like to get any tips how to resolve this issue. Maybe i choose the wrong way.
I want to know the right way of resolving this issue.
答案1
得分: 0
看起来返回的 SQL 结果如下:
un.id | un.name | un.description | unit_images
------+---------+----------------+---------------------------------------------------------------------
1 | Unit A | Description A | [(true, 'image1.jpg', 1), (false, 'image2.jpg', 2), (false, 'image3.jpg', 3)]
2 | Unit B | Description B | [(true, 'image4.jpg', 4), (true, 'image5.jpg', 5), (false, 'image6.jpg', 6)]
3 | Unit C | Description C | [(true, 'image7.jpg', 7), (false, 'image8.jpg', 8), (false, 'image9.jpg', 9)]
所以
`UnitImages []UnitImages `json:"unit_images" db:"unit_images"`
是正确的想法,你有一个 UnitImages 的数组。但是:
ID *int `json:"id" db:"id"`
Image *string `json:"image" db:"image"`
IsMain *bool `json:"is_main" db:"is_main"`
请注意,没有 SQL 列对应 id
、image
、is_main
,所以 Go 无法进行映射。
简单的解决方法是将 UnitImages 改为 []any,然后自己对数组中的内容进行转换,例如:
for _, item := range thing.UnitImages {
isMain := item[0].(bool)
image := item[1].(string)
id := item[2].(int64)
//TODO 使用这些变量做一些操作
}
或者你可以使用 `pg.StringArray` 类型。
<details>
<summary>英文:</summary>
Looks like the sql results comming back would be:
un.id | un.name | un.description | unit_images
------+---------+----------------+---------------------------------------------------------------------
1 | Unit A | Description A | [(true, 'image1.jpg', 1), (false, 'image2.jpg', 2), (false, 'image3.jpg', 3)]
2 | Unit B | Description B | [(true, 'image4.jpg', 4), (true, 'image5.jpg', 5), (false, 'image6.jpg', 6)]
3 | Unit C | Description C | [(true, 'image7.jpg', 7), (false, 'image8.jpg', 8), (false, 'image9.jpg', 9)]
So
UnitImages []UnitImages
json:"unit_images" db:"unit_images"`
Is the right idea, you have an array of UnitImages. BUT:
ID *int `json:"id" db:"id"`
Image *string `json:"image" db:"image"`
IsMain *bool `json:"is_main" db:"is_main"`
Notice there is no sql columns for `id`, `image`, `is_main` so go has no way to map them.
Easy fix to change UnitImages to []any and then cast the stuff in that array yourself like:
for _, item := range thing.UnitImages {
isMain := item[0].(bool)
image := item[1].(string)
id := item[2].(int64)
//TODO do something with these vars
}
Or you could use pg.StringArray
type.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论