postgresql - Golang 结构的 Postgres 数组
问题描述
我有以下 Go 结构:
type Bar struct {
Stuff string `db:"stuff"`
Other string `db:"other"`
}
type Foo struct {
ID int `db:"id"`
Bars []*Bar `db:"bars"`
}
所以Foo
包含一片Bar
指针。我在 Postgres 中也有以下表格:
CREATE TABLE foo (
id INT
)
CREATE TABLE bar (
id INT,
stuff VARCHAR,
other VARCHAR,
trash VARCHAR
)
我想LEFT JOIN
放在桌子上bar
并将其聚合为要存储在 struct 中的数组Foo
。我试过了:
SELECT f.*,
ARRAY_AGG(b.stuff, b.other) AS bars
FROM foo f
LEFT JOIN bar b
ON f.id = b.id
WHERE f.id = $1
GROUP BY f.id
但看起来ARRAY_AGG
函数签名不正确(function array_agg(character varying, character varying) does not exist
)。有没有办法在不单独查询的情况下做到这一点bar
?
解决方案
看起来你想要的是bars
一个 bar 对象数组来匹配你的 Go 类型。为此,您应该使用JSON_AGG
而不是ARRAY_AGG
因为ARRAY_AGG
仅适用于单列,并且在这种情况下会生成文本类型 ( TEXT[]
) 的数组。JSON_AGG
,另一方面,创建一个 json 对象数组。您可以将其与JSON_BUILD_OBJECT
仅选择所需的列相结合。
这是一个例子:
SELECT f.*,
JSON_AGG(JSON_BUILD_OBJECT('stuff', b.stuff, 'other', b.other)) AS bars
FROM foo f
LEFT JOIN bar b
ON f.id = b.id
WHERE f.id = $1
GROUP BY f.id
然后你必须处理在 Go 中解组 json,但除此之外你应该很高兴。
另请注意,在将 json 解组为结构时,Go 会为您忽略未使用的键,因此您可以根据bar
需要选择表上的所有字段来简化查询。像这样:
SELECT f.*,
JSON_AGG(TO_JSON(b.*)) AS bars -- or JSON_AGG(b.*)
FROM foo f
LEFT JOIN bar b
ON f.id = b.id
WHERE f.id = $1
GROUP BY f.id
如果您还想处理 inbar
中的记录没有条目的情况foo
,您可以使用:
SELECT f.*,
COALESCE(
JSON_AGG(TO_JSON(b.*)) FILTER (WHERE b.id IS NOT NULL),
'[]'::JSON
) AS bars
FROM foo f
LEFT JOIN bar b
ON f.id = b.id
WHERE f.id = $1
GROUP BY f.id
如果没有FILTER
,您将获得[NULL]
infoo
中没有相应行的行bar
,而FILTER
只是给您NULL
,然后只需使用它COALESCE
来转换为空的 json 数组。
推荐阅读
- html - 在 xPath 中使用 AND 和 NOT
- bootstrap-4 - Parsley JS 不适用于引导选择
- python - 赋值前引用的局部变量 - 令牌确认
- android - 使用 FusedLocationProviderClient 模拟和 Koin 进行依赖注入的单元测试
- git - git checkout 的声明式管道函数
- asp.net - 如何将请求时间设置为几个小时 - IIS 和 ASP:NET
- kubernetes - PriorityClass 不会将其值填充到 podSpec
- php - 如何根据php mysql中的id更新一行的总和
- c# - 特定目的地的默认映射
- mongodb - PowerShell Invoke-Command 未正确传递参数