PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment interroger les tableaux jsonb avec l'opérateur IN

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.