jsonb_agg: избегайте объектов, обернутых с помощью jsonb_build_object.

Я могу создавать объекты JSON, используя jsonb_build_object, как мне нужно. Например.

SELECT jsonb_build_object('id', id) FROM (SELECT generate_series(1,3) id) objects;

приводит к

jsonb_build_object
------------------
{"id": 1}
{"id": 2}
{"id": 3}

Но когда я хочу добавить их в массив, они оборачиваются в дополнительный объект, используя имя столбца в качестве ключа:

SELECT jsonb_build_object(
  'foo', 'bar',
  'collection', jsonb_agg(collection)
)
FROM (
  SELECT jsonb_build_object('id', id)
  FROM (
    SELECT generate_series(1,3) id
  ) objects
) collection;

приводит к

{"foo": "bar", "collection": [{"jsonb_build_object": {"id": 1}}, {"jsonb_build_object": {"id": 2}}, {"jsonb_build_object": {"id": 3}}]}

Как я могу получить

{"foo": "bar", "collection": [{"id": 1}, {"id": 2}, {"id": 3}]}

вместо?


person hfs    schedule 20.04.2017    source источник
comment
Это дубликат stackoverflow.com/q/30521196 , извините!   -  person hfs    schedule 20.04.2017


Ответы (1)


Используйте 1_. Вы также можете использовать псевдонимы, но дело в том, что collection относится ко всей строке, которая имеет (один) столбец с именем jsonb_build_object (по умолчанию), который представляет собой JSON, который вы хотите агрегировать.

С упрощением и псевдонимами ваш запрос может быть:

SELECT     jsonb_build_object(
             'foo', 'bar',
             'collection', jsonb_agg(js)
           )
FROM       generate_series(1,3) id
CROSS JOIN LATERAL jsonb_build_object('id', id) js;

Примечания:

  • LATERAL подразумевается, я просто написал это для ясности
  • такой псевдоним в предложении FROM создает таблицу и псевдоним столбца с тем же именем. Так что это эквивалентно jsonb_build_object('id', id) AS js(js)
person pozs    schedule 20.04.2017
comment
Создание псевдонима таблицы и столбца одновременно очень интересно, спасибо! Где я могу найти больше информации об этом? Документы не кажутся упомянуть об этом. - person Bergi; 04.10.2019
comment
@Bergi см. postgresql.org/docs/current/ -- Если псевдонимы столбцов не указаны, то для функции, возвращающей базовый тип данных, имя столбца совпадает с именем функции. Для функции, возвращающей составной тип, столбцы результатов получают имена отдельных атрибутов типа. -- хотя это только подразумевается, что когда вы создаете псевдоним имени функции, имя столбца по умолчанию изменяется вместе с ним. - person pozs; 05.10.2019
comment
Ах. Думаю, меня больше смутило обращение к элементу table_alias в синтаксисе как к имени функции :-) Я думал, что использование fn(…) AS t создаст таблицу t со столбцом fn. - person Bergi; 05.10.2019