web-dev-qa-db-fra.com

Tableau de requêtes JSON PostgreSQL contre plusieurs valeurs

Je veux écrire une requête contre jsonb dans Postgres qui, étant donné un tableau d'ID de clients, trouvera les groupes correspondants.

Étant donné cet exemple de tableau:

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

J'ai trouvé une question similaire ( PostgreSql JSONB SELECT contre plusieurs valeurs ) et j'ai réussi à obtenir ce que je veux sur un tableau simple en utilisant cette requête:

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

Cependant, je ne peux pas le faire fonctionner lorsque le tableau contient JSON objets:

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

Voici ce que j'attends de ma requête:

grp "First" -> client "1"

groupe "Troisième" -> client "5"

18
BartZ

Il existe un moyen: combiner opérateur de confinement @> avec la construction ANY :

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

Ou:

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

Il est essentiel de convertir le tableau en jsonb[] explicitement. Et notez que chaque élément est un JSON tableau à l'intérieur comme l'opérateur @> a besoin. C'est donc un tableau de tableaux JSON.

Vous pouvez utiliser un index pour cela:

Le le manuel indique explicitement que l'opérateur ?| est pour chaînes uniquement.

17