Go SQL карта 1: отношение M json массив к срезу - PullRequest
0 голосов
/ 10 июля 2020

У меня есть отношение product-image (1:M), и в основном я хочу сопоставить эти изображения с фрагментом моей структуры. Я использую библиотеку sqlx, чтобы упростить задачу.

Некоторое время я искал, и, возможно, лучший ответ был в этой теме: Эффективное сопоставление базы данных «один-ко-многим, многие-ко-многим» в структуру в Golang. Ответ с созданием представления и возвратом всего, как json, работает, но он кажется каким-то хакерским.

В идеале я хочу использовать postgres json_agg, чтобы вернуть массив json внутри столбец изображений, который будет соответствовать моему типу, чтобы я мог сканировать его.

Я делал это с nodejs несколько раз, но здесь я не знаю, как. Нужно ли мне реализовать собственные методы Scan и Value или есть более простой способ. Я не показывал это, но у меня также есть категория 1: 1, и я могу встроить эту категорию в продукт и выполнить левое соединение, и это работает с sqlx, но не с типом изображений.

Упрощенные модели

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"`
}

Таблицы БД

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)
);

Сейчас я пробую что-то вроде этого:

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)
}

Я получаю эту ошибку:

sql: Scan error on column index 26, name "images": unsupported Scan, storing driver.Value type []uint8 into type *model.ImageList

Это похоже на очень распространенный сценарий, но я не могу найти никаких примеров ... Или, наконец, я даже глуп для этого, потому что я могу просто выполнить forEach в JS и сделать около 50 запросов, чтобы получить все изображения для каждого продукта.

1 Ответ

0 голосов
/ 10 июля 2020

Одно решение для получения списка элементов может быть выполнено с использованием этой библиотеки сопоставления: carta

q := `SELECT p.*, img.id AS img_id, img.url AS img_url 
      FROM public.product p
      LEFT JOIN product_image img ON p.id = img.product_id`

    rows, err := sqlxdb.Query(q)
    if err != nil {
        fmt.Println(err)
    }

    var products []*model.Product
    carta.Map(rows, &products)

А для структуры img я бы использовал префикс db:"img_id "и так далее. , потому что я выбираю псевдонимом ...

...