Как создать пустой объект JSON в postgresql?

Datamodel

человек представлен в базе данных как строка мета-таблицы с именем и несколькими атрибутами, которые хранятся в таблице данных как пара ключ-значение (ключ и значение находятся в отдельных столбцах). Datamodel упрощенная модель данных

сейчас есть запрос для получения всех пользователей (имя) со всеми их атрибутами (сведения). Атрибуты возвращаются как объект 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 (
  JOIN 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;

теперь проблема, с которой я сталкиваюсь, заключается в том, что пользователям нравится Томас, которые не имеют никаких атрибутов, хранящихся в таблица, не отображаются с моей функцией выбора. Это потому, что он делает только JOIN и LEFT OUTER JOIN.

если бы я использовал LEFT OUTER JOIN тогда я сталкиваюсь с проблемой, что json_object_agg попробовать агрегировать NULL ценности и умирает с ошибкой.

подходы

1. Возвращает пустой список ключей и значений

поэтому я попытался проверить, если пользователя NULL и верните пустой массив so json_object_agg просто создаст пустой JSON.

но на самом деле нет функции для создания пустого массива в SQL. Ближе всего я нашел следующее:--27-->

select '{}'::text[];

In комбинация с 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 не проверяет, что массив пуст.

Qustion

Итак, есть ли функция, чтобы проверить, является ли объединенный столбец пустым, и если да, верните просто простой объект JSON?

или есть ли другое решение, которое решило бы мою проблему?

1 ответов


использовать left join С coalesce(). По умолчанию используется значение '{}'::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 1
    ) d
on m.id = d.fk_id;

  name   |                data                
---------+------------------------------------
 Florian | { "age" : "25" }
 Marcus  | { "age" : "25", "color" : "blue" }
 Thomas  | {}
(3 rows)