sql >> Base de Datos >  >> RDS >> PostgreSQL

LIKE consulta sobre elementos de matriz jsonb plana

SELECT *
FROM   posts p
WHERE  EXISTS (
   SELECT FROM jsonb_array_elements_text(p.tags) tag
   WHERE  tag LIKE '%TAG%'
   );

Relacionado, con explicación:

  • Buscar en una matriz JSON un objeto que contenga un valor que coincida con un patrón

O más simple con @? operador desde que Postgres 12 implementó 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")';

El operador @? es solo un envoltorio alrededor de la función jsonb_path_exists() . Así que esto es equivalente:

...
WHERE  jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');

Tampoco tiene soporte de índice. (Se puede agregar para @? operador más tarde, pero no allí en la página 13, todavía). Entonces esas consultas son lentas para tablas grandes. Un diseño normalizado, como ya sugirió Laurenz, sería superior, con un índice de trigrama:

  • Variaciones de rendimiento de consultas LIKE de PostgreSQL

Solo por coincidencia de prefijos (LIKE 'TAG%' , sin comodín inicial), puede hacer que funcione con un índice de texto completo :

CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));

Y una consulta coincidente:

SELECT *
FROM   posts p
WHERE  to_tsvector('simple', tags)  @@ 'TAG:*'::tsquery

O usa el english diccionario en lugar de simple (o lo que se ajuste a su caso) si desea derivación para el idioma inglés natural.

to_tsvector(json(b)) requiere Postgres 10 o posterior.

Relacionado:

  • Obtener una coincidencia parcial de la columna TSVECTOR indexada por GIN
  • Coincidencia de patrones con LIKE, SIMILAR TO o expresiones regulares en PostgreSQL