Кратък отговор
Можете да използвате функцията jsonb_array_elements()
в странично съединение и използвайте неговия резултат value
в сложни изрази в WHERE
клауза:
SELECT t.*
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('b', 'd')
AND value->>'label1' IN ('2', '3')
Различими
Заявката може да върне дублирани редове, когато условията за филтриране са изпълнени в повече от един елемент от масива в един ред, напр.
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)
Следователно може да е разумно да използвате DISTINCT
в SELECT
списък:
SELECT DISTINCT t.*
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
или EXISTS
в WHERE
клауза, която може да е малко по-бърза:
SELECT t.*
FROM test t
WHERE EXISTS (
SELECT
FROM jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
)
Можете също да изберете съответстващи елементи на масива в случаите, когато е необходима тази информация:
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)
Изпълнение
jsonb_array_elements()
функцията е скъпа. За по-големи таблици използването на функцията може да бъде под въпрос поради голямото натоварване на сървъра и дългото време за изпълнение на заявка.
Докато GIN индекс може да се използва за заявки с @>
оператор:
CREATE INDEX ON test USING GIN (test_content)
в случай на функция това не е възможно. Заявките, поддържани от индекса, могат да бъдат до няколко десетки пъти по-бързи от тези, използващи функцията.