SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Connexe, avec explication :
- Rechercher dans un tableau JSON un objet contenant une valeur correspondant à un modèle
Ou plus simple avec le @?
opérateur depuis Postgres 12 implémenté 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")';
L'opérateur @?
est juste un wrapper autour de la fonction jsonb_path_exists()
. Donc c'est équivalent :
...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Ni l'un ni l'autre n'a de support d'index. (Peut être ajouté pour le @?
opérateur plus tard, mais pas encore à la page 13). Ces requêtes sont donc lentes pour les grandes tables. Une conception normalisée, comme Laurenz l'a déjà suggéré, serait supérieure - avec un index trigramme :
- Variations des performances des requêtes PostgreSQL LIKE
Pour seulement la correspondance de préfixe (LIKE 'TAG%'
, sans caractère générique de début), vous pouvez le faire fonctionner avec un index de texte intégral :
CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
Et une requête correspondante :
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Ou utilisez le english
dictionnaire au lieu de simple
(ou tout ce qui convient à votre cas) si vous voulez un stemming pour la langue anglaise naturelle.
to_tsvector(json(b))
nécessite Postgres 10 ou plus tard.
Connexe :
- Obtenir une correspondance partielle à partir de la colonne TSVECTOR indexée GIN
- Mise en correspondance de modèles avec LIKE, SIMILAR TO ou des expressions régulières dans PostgreSQL