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"
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.