I have a product-image (1:M)
relation and basically i want to map those images to a slice in my struct. I am using sqlx library to make it bit easier.
I searched for a while and maybe the best answer was in this thread: Efficiently mapping one-to-many many-to-many database to struct in Golang. The answer with creating the view and returning everything as a json works but it feels somehow hacky.
Ideally what i want to do is use postgres json_agg
to return the json array inside the images column that would match my type so i could scan into it.
I did this with nodejs several times but here i don't know how. Do i need to implement custom Scan
and Value
methods or is there a simpler way. I didn't show this but i also have a category that is 1:1 and i can embed that category in product and do a left join and it works with sqlx, but not with images type.
Simplified models
type Image struct {
ID int,
URL string,
ProductID int
}
type ImageList []*Image
type Product struct {
ID int `db:"id"`
Name string `db:"name"`
Images ImageList `db:"images"`
}
DB Tables
create table product (
id int generated always as identity primary key,
name varchar(255),
);
create table product_image (
id int generated always as identity primary key,
url text not null,
product_id int references product(id)
);
I am trying something like this now:
q := `SELECT
p.*,
COALESCE(JSON_AGG(img.*) FILTER (WHERE img.product_id IS NOT NULL), '[]'::json) AS images
FROM product p
LEFT JOIN product_image img ON p.id = img.product_id
WHERE p.id = 1
GROUP BY p.id`
var p Product
if err := sqlxdb.Get(&p, q); err != nil {
fmt.Printf("Error: %v\n", err)
}
I get this error:
sql: Scan error on column index 26, name "images": unsupported Scan, storing driver.Value type []uint8 into type *model.ImageList
This seems like a super common scenario and yet i can't find any examples... Or finally am i even stupid for doing this because i can just do forEach in JS and do like 50 queries to fetch all the images for every product.