Réponse courte
Vous pouvez utiliser la fonction jsonb_array_elements()
dans une jointure latérale et utiliser son résultat value
dans des expressions complexes dans le WHERE
clause :
SELECT t.*
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('b', 'd')
AND value->>'label1' IN ('2', '3')
Distinct
La requête peut renvoyer des lignes dupliquées lorsque les conditions de filtre sont remplies dans plus d'un élément du tableau dans une seule ligne, par exemple
SELECT t.*
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
id | test_content
--------------------------------------+----------------------------------------------------------------
aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | [{"label": "a", "label1": "1"}, {"label": "b", "label1": "2"}]
aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | [{"label": "a", "label1": "1"}, {"label": "b", "label1": "2"}]
(2 rows)
Il peut donc être raisonnable d'utiliser DISTINCT
dans le SELECT
liste :
SELECT DISTINCT t.*
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
ou EXISTS
dans le WHERE
clause, qui peut être un peu plus rapide :
SELECT t.*
FROM test t
WHERE EXISTS (
SELECT
FROM jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
)
Vous pouvez également sélectionner des éléments de tableau correspondants dans les cas où ces informations sont nécessaires :
SELECT id, value
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
id | value
--------------------------------------+-------------------------------
aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | {"label": "a", "label1": "1"}
aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | {"label": "b", "label1": "2"}
(2 rows)
Performances
Le jsonb_array_elements()
la fonction coûte cher. Pour les tables plus volumineuses, l'utilisation de la fonction peut être discutable en raison de la charge importante du serveur et du long temps d'exécution d'une requête.
Alors qu'un index GIN peut être utilisé pour les requêtes avec le @>
opérateur :
CREATE INDEX ON test USING GIN (test_content)
dans le cas de la fonction, cela n'est pas possible. Les requêtes prises en charge par l'index peuvent être jusqu'à plusieurs dizaines de fois plus rapides que celles utilisant la fonction.