使用 jsonb_agg/jsonb_build_object 解析为内部结构
Using jsonb_agg/jsonb_build_object to parse to inner structs
每当我尝试获取 (select/scan) 组(外部结构)及其协作者(内部结构)时,我都会收到以下错误:
// sql: Scan error on column index ..., name "collaborators": unsupported Scan, storing driver.Value type []uint8 into type *[]User
我正在使用 sqlx(带有 pgx 驱动程序)。
从数据库获取的代码是:
func (psql *Postgres) GetGroups(someParam string) ([]Group, error) {
groups := []Group{}
err := psql.db.Unsafe().Select(&groups, <the query ...>, someParam)
....
}
type Postgres struct {
db *sqlx.DB
config *config.PostgresDB
timeout time.Duration
}
这是 SQL 查询:
SELECT groups.id,
groups.title,
JSONB_AGG(JSONB_BUILD_OBJECT(
'id', u.id,
'first_name', u.first_name,
'last_name', u.last_name,
'user_pic_url', u.user_pic_url)) as collaborators
FROM groups
JOIN user_group_permissions p
ON p.group_id = groups.id
JOIN users u
ON u.id = p.user_id
这些是结构:
type Group struct {
Id string `json:"id" db:"id"`
Title string `json:"title" db:"title"`
Collaborators []User `json:"collaborators" db:"collaborators"`
}
type User struct {
Id string `json:"id" db:"id"`
FirstName string `json:"first_name" db:"first_name"`
LastName string `json:"last_name" db:"last_name"`
ProfilePhoto *string `json:"profile_photo" db:"user_pic_url"`
}
我有一个简单的组 table ,一个用户 table 和 table 代表对该组具有权限的所有用户:
CREATE TABLE groups (
id int UNIQUE NOT NULL generated always as identity,
title text
)
CREATE TABLE users (
id bigint UNIQUE NOT NULL generated always as identity,
first_name text NOT NULL,
last_name text NOT NULL,
user_pic_url text
)
CREATE TABLE user_group_permissions (
group_id unsigned_int,
user_id unsigned_bigint,
permission unsigned_smallint,
)
CREATE DOMAIN unsigned_smallint AS smallint
CHECK(VALUE >= 0 AND VALUE < 32767);
CREATE DOMAIN unsigned_int AS int
CHECK(VALUE >= 0 AND VALUE < 2147483647);
CREATE DOMAIN unsigned_bigint AS bigint
CHECK(VALUE >= 0 AND VALUE < 9223372036854775807);
import "encoding/json"
type Group struct {
Id string `json:"id" db:"id"`
Title string `json:"title" db:"title"`
Collaborators UserList `json:"collaborators" db:"collaborators"`
}
type User struct {
Id string `json:"id" db:"id"`
FirstName string `json:"first_name" db:"first_name"`
LastName string `json:"last_name" db:"last_name"`
ProfilePhoto *string `json:"profile_photo" db:"user_pic_url"`
}
type UserList []User
func (list *UserList) Scan(src interface{}) error {
var data []byte
switch v := src.(type) {
case []byte:
data = v
case string:
data = []byte(v)
default:
return nil // or return some error
}
return json.Unmarshal(data, list)
}
每当我尝试获取 (select/scan) 组(外部结构)及其协作者(内部结构)时,我都会收到以下错误:
// sql: Scan error on column index ..., name "collaborators": unsupported Scan, storing driver.Value type []uint8 into type *[]User
我正在使用 sqlx(带有 pgx 驱动程序)。
从数据库获取的代码是:
func (psql *Postgres) GetGroups(someParam string) ([]Group, error) {
groups := []Group{}
err := psql.db.Unsafe().Select(&groups, <the query ...>, someParam)
....
}
type Postgres struct {
db *sqlx.DB
config *config.PostgresDB
timeout time.Duration
}
这是 SQL 查询:
SELECT groups.id,
groups.title,
JSONB_AGG(JSONB_BUILD_OBJECT(
'id', u.id,
'first_name', u.first_name,
'last_name', u.last_name,
'user_pic_url', u.user_pic_url)) as collaborators
FROM groups
JOIN user_group_permissions p
ON p.group_id = groups.id
JOIN users u
ON u.id = p.user_id
这些是结构:
type Group struct {
Id string `json:"id" db:"id"`
Title string `json:"title" db:"title"`
Collaborators []User `json:"collaborators" db:"collaborators"`
}
type User struct {
Id string `json:"id" db:"id"`
FirstName string `json:"first_name" db:"first_name"`
LastName string `json:"last_name" db:"last_name"`
ProfilePhoto *string `json:"profile_photo" db:"user_pic_url"`
}
我有一个简单的组 table ,一个用户 table 和 table 代表对该组具有权限的所有用户:
CREATE TABLE groups (
id int UNIQUE NOT NULL generated always as identity,
title text
)
CREATE TABLE users (
id bigint UNIQUE NOT NULL generated always as identity,
first_name text NOT NULL,
last_name text NOT NULL,
user_pic_url text
)
CREATE TABLE user_group_permissions (
group_id unsigned_int,
user_id unsigned_bigint,
permission unsigned_smallint,
)
CREATE DOMAIN unsigned_smallint AS smallint
CHECK(VALUE >= 0 AND VALUE < 32767);
CREATE DOMAIN unsigned_int AS int
CHECK(VALUE >= 0 AND VALUE < 2147483647);
CREATE DOMAIN unsigned_bigint AS bigint
CHECK(VALUE >= 0 AND VALUE < 9223372036854775807);
import "encoding/json"
type Group struct {
Id string `json:"id" db:"id"`
Title string `json:"title" db:"title"`
Collaborators UserList `json:"collaborators" db:"collaborators"`
}
type User struct {
Id string `json:"id" db:"id"`
FirstName string `json:"first_name" db:"first_name"`
LastName string `json:"last_name" db:"last_name"`
ProfilePhoto *string `json:"profile_photo" db:"user_pic_url"`
}
type UserList []User
func (list *UserList) Scan(src interface{}) error {
var data []byte
switch v := src.(type) {
case []byte:
data = v
case string:
data = []byte(v)
default:
return nil // or return some error
}
return json.Unmarshal(data, list)
}