Kort antwoord
U kunt de functie jsonb_array_elements()
. gebruiken in een laterale samenvoeging en gebruik het resultaat value
in complexe uitdrukkingen in de WHERE
clausule:
SELECT t.*
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('b', 'd')
AND value->>'label1' IN ('2', '3')
Verschillend
De query kan dubbele rijen retourneren wanneer aan de filtervoorwaarden is voldaan in meer dan één element van de array in een enkele rij, bijvoorbeeld
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)
Daarom kan het redelijk zijn om DISTINCT
. te gebruiken in de SELECT
lijst:
SELECT DISTINCT t.*
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
of EXISTS
in de WHERE
clausule, die misschien wat sneller is:
SELECT t.*
FROM test t
WHERE EXISTS (
SELECT
FROM jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
)
U kunt ook overeenkomende array-elementen selecteren in gevallen waarin deze informatie nodig is:
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)
Prestaties
De jsonb_array_elements()
functie is duur. Voor grotere tabellen kan het gebruik van de functie twijfelachtig zijn vanwege de zware serverbelasting en de lange uitvoeringstijd van een query.
Hoewel een GIN-index kan worden gebruikt voor zoekopdrachten met de @>
operator:
CREATE INDEX ON test USING GIN (test_content)
bij de functie is dit niet mogelijk. Query's die door de index worden ondersteund, kunnen tot enkele tientallen keren sneller zijn dan die waarbij de functie wordt gebruikt.