Можно ли установить значение массива Postgres по указанному индексу без учета длины? - PullRequest
0 голосов
/ 30 января 2020

В моем столбце data есть следующая структура данных JSONB:

data = {
  field1,
  field2,
  ...,
  items: [id1, id2, ...id3],
}

И необходимо добавить элемент в массив items, указав его индекс. Может быть несколько параллельных запросов к API, каждый из которых предоставляет идентификатор и свой индекс , поэтому невозможно просто заменить старый data новым. Потому что в коде API мы не знаем, каково текущее количество предметов.

Помогите мне, пожалуйста. Как мы можем справиться с этой ситуацией, используя Postgres?

Например, здорово использовать что-то вроде splice в Javascript, когда вы можете установить значение по индексу и заполнить остальное null ценности. Но возможно ли что-нибудь подобное в Postgres?

Каких результатов я ожидаю (пример):

  1. первый запрос, index = 5, массив в db = [null, null , ноль, ноль, ноль, идентификатор]
  2. второй запрос, индекс = 2, массив в db = [ноль, ноль, идентификатор, ноль, ноль, идентификатор]
  3. третий запрос, индекс = 0, массив в db = [id, null, id, null, null, id]
  4. четвертый запрос, index = 3, массив в db = [id, null, id, id, null, id]
  5. пятый запрос, index = 2, массив в db = [id, null, id, id, id, id] *
  6. шестой запрос, index = 1, массив в db = [id, id, id, id, id, id]

и т. д.

1 Ответ

1 голос
/ 30 января 2020

Может быть несколько параллельных запросов к API, каждый из которых предоставляет идентификатор и свой индекс, поэтому невозможно просто заменить старые данные новыми.

Это единственное, что возможно в PostgreSQL. Отдельные компоненты JSONB не могут быть отредактированы на месте, вам нужно извлечь старое значение JSONB, изменить его и заменить новым.

Вы, вероятно, можете делать то, что хотите, с помощью jsonb_set .

update mytable set myjsonb=jsonb_set(myjsonb,'{items,3}','"id3"') where myid=6

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

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

BEGIN;
select myjsonb from mytable where myid=6 for update;
<do stuff here in the client>
update mytable set myjsonb=:newvalue where myid=6;
COMMIT;
...