Krátká odpověď
Můžete použít funkci jsonb_array_elements()
v bočním spojení a použijte jeho výsledek value
ve složitých výrazech v WHERE
klauzule:
SELECT t.*
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('b', 'd')
AND value->>'label1' IN ('2', '3')
Odlišné
Dotaz může vracet duplicitní řádky, pokud jsou splněny podmínky filtru ve více než jednom prvku pole v jednom řádku, např.
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)
Proto může být rozumné použít DISTINCT
v SELECT
seznam:
SELECT DISTINCT t.*
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
nebo EXISTS
v WHERE
klauzule, která může být o něco rychlejší:
SELECT t.*
FROM test t
WHERE EXISTS (
SELECT
FROM jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
)
Můžete také vybrat odpovídající prvky pole v případech, kdy jsou tyto informace potřeba:
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)
Výkon
jsonb_array_elements()
funkce je drahá. U větších tabulek může být použití funkce sporné kvůli velkému zatížení serveru a dlouhé době provádění dotazu.
Zatímco index GIN lze použít pro dotazy s @>
operátor:
CREATE INDEX ON test USING GIN (test_content)
v případě funkce to není možné. Dotazy podporované indexem mohou být až několik desítekkrát rychlejší než dotazy využívající tuto funkci.