PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

LIKE consulta em elementos da matriz jsonb plana

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