SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Relacionado, com explicação:
- Pesquisar uma matriz JSON por um objeto que contenha um valor que corresponda a um padrão
Ou mais simples com o
@?
operador desde que o Postgres 12 implementou 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")';
O operador
@?
é apenas um wrapper em torno da função jsonb_path_exists()
. Então isso é equivalente:...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Nem tem suporte de índice. (Pode ser adicionado para o
@?
operador mais tarde, mas ainda não está na página 13). Portanto, essas consultas são lentas para tabelas grandes. Um design normalizado, como Laurenz já sugeriu, seria superior - com um índice de trigrama:- Variações de desempenho de consulta PostgreSQL LIKE
Apenas para correspondência de prefixo (
LIKE 'TAG%'
, sem caractere curinga à esquerda), você pode fazê-lo funcionar com um índice de texto completo :CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
E uma consulta correspondente:
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Ou use o
english
dicionário em vez de simple
(ou o que for mais adequado ao seu caso) se você quiser derivar para o idioma inglês natural. to_tsvector(json(b))
requer Postgres 10 ou mais tarde. Relacionado:
- Obter correspondência parcial da coluna TSVECTOR indexada por GIN
- Correspondência de padrões com LIKE, SIMILAR TO ou expressões regulares no PostgreSQL