Массив запросов PostgreSQL JSON для нескольких значений

17

Я хочу написать запрос к jsonbтипу в Postgres, который, учитывая массив идентификаторов клиентов, найдет соответствующие группы.

Учитывая этот пример таблицы:

CREATE TABLE grp(d JSONB NOT NULL);

INSERT INTO grp VALUES
   ('{"name":"First","arr":["foo"], "customers":[{"id":"1", "name":"one"},{"id":"2", "name":"two"}]}')
 , ('{"name":"Second","arr":["foo","bar"], "customers":[{"id":"3", "name":"three"},{"id":"4", "name":"four"}]}')
 , ('{"name":"Third","arr":["bar","baz"], "customers":[{"id":"5", "name":"five"},{"id":"6", "name":"seven"}]}');

Я нашел похожий вопрос ( PostgreSql JSONB SELECT для нескольких значений ) и сумел добиться желаемого для простого массива с помощью этого запроса:

SELECT d FROM grp WHERE d->'arr' ?| ARRAY['foo', 'bar'];

Однако я не могу заставить его работать, когда массив содержит объекты JSON :

SELECT d FROM grp WHERE d->'customers' ?| ARRAY['{"id":"1"}', '{"id":"5"}'];

Вот что я ожидаю от моего запроса:

Группа "Первый" -> Заказчик "1"

группа "Третий" -> клиент "5"

Бартц
источник

Ответы:

16

Есть способ: объединить оператор сдерживания@> с ANYконструкцией :

SELECT d
FROM   grp
WHERE  d->'customers' @> ANY (ARRAY ['[{"id":"1"}]', '[{"id":"5"}]']::jsonb[]);

Или:

...
WHERE d->'customers' @> ANY ('{"[{\"id\": \"1\"}]","[{\"id\": \"5\"}]"}'::jsonb[]);

Важно привести массив к jsonb[]явному. И обратите внимание, что каждый элемент является массивом JSON внутри, как того @>требует оператор . Так что это массив массивов JSON.

Вы можете использовать индекс для этого:

В руководстве явно указано, что оператор ?|предназначен только для строк .

Эрвин Брандштеттер
источник