Matriz de consulta PostgreSQL JSON em relação a vários valores

16

Quero escrever uma consulta contra o jsonbtipo no Postgres que, dada uma matriz de IDs de clientes, encontre grupos correspondentes.

Dado este exemplo de tabela:

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"}]}');

Eu encontrei uma pergunta semelhante ( PostgreSql JSONB SELECT contra vários valores ) e consegui alcançar o que eu quero em uma matriz simples usando esta consulta:

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

No entanto, não posso fazê-lo funcionar quando, quando a matriz contém objetos JSON :

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

Aqui está o que eu espero da minha consulta:

grp "Primeiro" -> cliente "1"

grp "Terceiro" -> cliente "5"

BartZ
fonte

Respostas:

15

Existe uma maneira: combine o operador de contenção@> com a ANYconstrução :

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

Ou:

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

É essencial transmitir a matriz jsonb[]explicitamente. E observe que cada elemento é uma matriz JSON interna como o operador @>exige. Portanto, é uma matriz de matrizes JSON.

Você pode usar um índice para isso:

O manual afirma explicitamente que o operador ?|é apenas para seqüências de caracteres .

Erwin Brandstetter
fonte