SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Свързано, с обяснение:
- Търсете в JSON масив за обект, съдържащ стойност, съответстваща на шаблон
Или по-просто с @?
оператор, тъй като Postgres 12 имплементира SQL/JSON:
SELECT *
-- optional to show the matching item:
-- , jsonb_path_query_first(tags, '$[*] ? (@ like_regex "^ tag" flag "i")')
FROM posts
WHERE tags @? '$[*] ? (@ like_regex "TAG")';
Операторът @?
е просто обвивка около функцията jsonb_path_exists()
. Така че това е еквивалентно:
...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Нито един от тях няма поддръжка на индекси. (Може да се добави за @?
оператор по-късно, но все още не е там в стр. 13). Така че тези заявки са бавни за големи таблици. Нормализиран дизайн, както Лоренц вече предложи, би бил по-добър - с индекс на триграма:
- Варианти на ефективността на заявката като PostgreSQL LIKE
Само за съвпадение на префикса (LIKE 'TAG%'
, без водещ заместващ знак), можете да го накарате да работи с пълен текстов индекс :
CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
И съвпадаща заявка:
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Или използвайте english
речник вместо simple
(или каквото е подходящо за вашия случай), ако искате да използвате естествен английски език.
to_tsvector(json(b))
изисква Postgres 10 или по-късно.
Свързано:
- Вземете частично съвпадение от GIN индексирана колона TSVECTOR
- Съвпадение на образец с LIKE, SIMILAR TO или регулярни изрази в PostgreSQL