SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Correlati, con spiegazione:
- Cerca in un array JSON un oggetto contenente un valore che corrisponde a un pattern
O più semplice con il @?
operatore poiché Postgres 12 ha implementato 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'operatore @?
è solo un wrapper attorno alla funzione jsonb_path_exists()
. Quindi questo è equivalente:
...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Nessuno dei due ha il supporto dell'indice. (Può essere aggiunto per @?
operatore più tardi, ma non è ancora presente a pagina 13). Quindi quelle query sono lente per i tavoli grandi. Un design normalizzato, come già suggerito da Laurenz, sarebbe superiore, con un indice trigram:
- Variazioni delle prestazioni delle query LIKE di PostgreSQL
Solo per corrispondenza dei prefissi (LIKE 'TAG%'
, nessun carattere jolly iniziale), potresti farlo funzionare con un indice di testo completo :
CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
E una query corrispondente:
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Oppure usa l'english
dizionario invece di simple
(o qualunque cosa si adatti al tuo caso) se vuoi derivare per la lingua inglese naturale.
to_tsvector(json(b))
richiede Postgres 10 o successivo.
Correlati:
- Ottieni una corrispondenza parziale dalla colonna TSVECTOR indicizzata GIN
- Corrispondenza del modello con LIKE, SIMILAR TO o espressioni regolari in PostgreSQL