SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Relateret, med forklaring:
- Søg i et JSON-array efter et objekt, der indeholder en værdi, der matcher et mønster
Eller enklere med @?
operatør siden Postgres 12 implementerede 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")';
Operatøren @?
er blot en indpakning omkring funktionen jsonb_path_exists()
. Så dette svarer til:
...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Ingen af dem har indeksstøtte. (Kan tilføjes for @?
operatør senere, men ikke der på s. 13 endnu). Så disse forespørgsler er langsomme for store borde. Et normaliseret design, som Laurenz allerede har foreslået, ville være overlegent - med et trigramindeks:
- PostgreSQL LIKE forespørgselsydeevnevariationer
Til kun præfiksmatchning (LIKE 'TAG%'
, ingen indledende jokertegn), kan du få det til at fungere med et fuldtekstindeks :
CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
Og en matchende forespørgsel:
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Eller brug den english
ordbog i stedet for simple
(eller hvad der passer til dit tilfælde), hvis du ønsker at stamme fra naturligt engelsk sprog.
to_tsvector(json(b))
kræver Postgres 10 eller senere.
Relateret:
- Få delvis match fra GIN-indekseret TSVECTOR-kolonne
- Mønstermatching med LIKE, SIMILAR TO eller regulære udtryk i PostgreSQL