Postgres: создание объекта jsonb с заданным набором ключей и значением по умолчанию - PullRequest
0 голосов
/ 12 декабря 2018

Я использую PostgreSQL 9.6.У меня есть массив типа ARRAY['a', 'b']::text[], который происходит из кода приложения и немного преобразуется в SQL, поэтому я не знаю его длины в коде приложения.

В таблице у меня есть поле типа jsonb, которое мне нужно установить для объекта json, где ключами являются значения из данного массива, а значения все одинаковые иравно текущей отметке времени, т.е.

| id | my_field                                         |
---------------------------------------------------------
| 1  | {"a":"1544605046.21065", "b":"1544605046.21065"} |

Я пытаюсь найти запрос на обновление для выполнения этого обновления, например, что-то вроде

UPDATE mytable 
SET my_field = some_function(ARRAY['a','b']::text[], EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)
WHERE <some_condition>;

Я смотрел на jsonb_build_object функцию, котораяможет помочь мне, если бы я мог преобразовать свой массив, чередуя его элементы с текущей меткой времени, однако я не нашел способа сделать это.

Обратите внимание, что у меня, вероятно, будут сотни тысячзаписи для обновления, поэтому я ищу быстрое внедрение.

Буду признателен за любые советы по этому вопросу.

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

demo: db <> fiddle

UPDATE my_table
SET my_field = s.json_data
FROM (
    SELECT jsonb_object_agg(key, extract(epoch from current_timestamp)) as json_data
    FROM unnest(array['a', 'b']) as u(key)
) s
WHERE <some condition>
  1. Чтобы использовать элемент массива в качестве ключей для объекта json, вам необходимо разделить их на unnest.Это создает одну строку для каждого элемента.
  2. Агрегирование строк с помощью jsonb_object_agg(key, value).В качестве ключа вы берете столбец элементов массива.Как значение current_timestamp.Эта функция объединяется в ожидаемый синтаксис.
  3. Помещение этого в подзапрос позволяет вам выполнить обновление.
0 голосов
/ 12 декабря 2018

Используйте jsonb_object_agg() для неперемещенных элементов массива в качестве ключей:

select jsonb_object_agg(key, extract(epoch from current_timestamp))
from unnest(array['a', 'b']) as u(key)

                jsonb_object_agg                
------------------------------------------------
 {"a": 1544607022.84596, "b": 1544607022.84596}
(1 row)

Поскольку агрегатные функции не разрешены в UPDATE, вы должны создать простую функцию:

create or replace function my_arr_to_jsonb(text[])
returns jsonb language sql immutable as $$
    select jsonb_object_agg(key, extract(epoch from current_timestamp))
    from unnest($1) as u(key)
$$;

-- example use:
update my_table
set my_field = my_arr_to_jsonb(array['a', 'b'])
where id = 1;
...