如何在postgresql中创建一个空的JSON对象?

问题描述 投票:0回答:1

数据模型

一个人在数据库中表示为元表行,具有名称和多个属性,这些属性作为键值对存储在数据表中(键和值位于单独的列中)。 简化的数据模型

现在有一个查询来检索所有用户(name)及其所有属性(data)。属性在单独的列中作为 JSON 对象返回。这是一个例子:

name      data
Florian   { "age":25 }
Markus    { "age":25, "color":"blue" }
Thomas    {}

SQL 命令如下所示:

SELECT
  name,
  json_object_agg(d.key, d.value) AS data
FROM meta AS m
JOIN (
  SELECT d.fk_id, d.key, d.value AS value FROM data AS d
  ) AS d
ON d.fk_id = m.id
GROUP BY m.name;

问题

现在我面临的问题是,像 Thomas 这样没有任何属性存储在 key-value 表中的用户,不会通过我的选择功能显示。这是因为它只执行

JOIN
而没有
LEFT OUTER JOIN

如果我使用

LEFT OUTER JOIN
那么我会遇到问题,即
json_object_agg
尝试聚合
NULL
值并因错误而死亡。

方法

1.返回一个空的键和值列表

因此,我尝试检查用户的 key-column 是否为

NULL
并返回一个空数组,以便
json_object_agg
将创建一个空的 JSON 对象。

但是 SQL 中并没有真正创建空数组的函数。我发现的最近的东西是这样的:

select '{}'::text[];

COALESCE
结合使用,查询如下所示:

json_object_agg(COALESCE(d.key, '{}'::text[]), COALESCE(d.value, '{}'::text[])) AS data

但是如果我尝试使用它,我会收到以下错误:

ERROR:  COALESCE types text and text[] cannot be matched
LINE 10:     json_object_agg(COALESCE(d.key, '{}'::text[]), COALES...
                                                ^
Query failed
PostgreSQL said: COALESCE types text and text[] cannot be matched

所以看起来在运行时

d.key
是单个值,而不是数组。

2.拆分 JSON 创建并返回一个空列表

所以我尝试采用

json_object_agg
并将其替换为
json_object
,这不会为我聚合密钥:

json_object(COALESCE(array_agg(d.key), '{}'::text[]), COALESCE(array_agg(d.value), '{}'::text[])) AS data

但是我得到了错误

null value not allowed for object key
。所以
COALESCE
不会检查数组是否为空。

问题

那么,是否有一个函数可以检查连接列是否为空,如果是则仅返回一个简单的 JSON 对象?

或者有其他解决方案可以解决我的问题吗?

json postgresql aggregate-functions postgresql-9.4
1个回答
37
投票

使用左连接和

coalesce()
以及空 json 对象
'{}'::json
作为默认值。

select 
    name, 
    coalesce(d.data, '{}'::json) as data
from meta m
left join (
    select 
        fk_id, 
        json_object_agg(d.key, d.value) as data
    from data d
    group by fk_id
    ) d
on m.id = d.fk_id;

db<>fiddle 中测试它。

© www.soinside.com 2019 - 2024. All rights reserved.