Conjunto de consultas JSON de PostgreSQL contra múltiples valores

17

Quiero escribir una consulta contra el jsonbtipo en Postgres que, dado un conjunto de ID de clientes, encontrará los grupos correspondientes.

Dada esta tabla de ejemplo:

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

Encontré una pregunta similar ( PostgreSql JSONB SELECT contra múltiples valores ) y logré lograr lo que quiero en una matriz simple usando esta consulta:

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

Sin embargo, no puedo hacer que funcione cuando la matriz contiene objetos JSON :

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

Esto es lo que espero de mi consulta:

grp "Primero" -> cliente "1"

grp "Tercero" -> cliente "5"

BartZ
fuente

Respuestas:

16

Hay una manera: combinar el operador de contención@> con la ANYconstrucción :

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

O:

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

Es esencial emitir la matriz jsonb[]explícitamente. Y tenga en cuenta que cada elemento es una matriz JSON en el interior como lo @>requiere el operador . Entonces es una matriz de matrices JSON.

Puede usar un índice para esto:

El manual establece explícitamente que el operador ?|es solo para cadenas .

Erwin Brandstetter
fuente