SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Gerelateerd, met uitleg:
- Zoek in een JSON-array naar een object dat een waarde bevat die overeenkomt met een patroon
Of eenvoudiger met de @?
operator sinds Postgres 12 SQL/JSON heeft geïmplementeerd:
SELECT *
-- optional to show the matching item:
-- , jsonb_path_query_first(tags, '$[*] ? (@ like_regex "^ tag" flag "i")')
FROM posts
WHERE tags @? '$[*] ? (@ like_regex "TAG")';
De operator @?
is slechts een wrapper rond de functie jsonb_path_exists()
. Dit is dus equivalent:
...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Geen van beide heeft indexondersteuning. (Mag worden toegevoegd voor de @?
operator later, maar nog niet in pg 13). Dus die query's zijn traag voor grote tabellen. Een genormaliseerd ontwerp, zoals Laurenz al suggereerde, zou superieur zijn - met een trigram-index:
- PostgreSQL LIKE prestatievariaties voor query's
Voor slechts voorvoegselovereenkomst (LIKE 'TAG%'
, geen leidende wildcard), zou u het kunnen laten werken met een volledige tekstindex :
CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
En een overeenkomende zoekopdracht:
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Of gebruik de english
woordenboek in plaats van simple
(of wat dan ook bij je past) als je wilt stammen voor natuurlijke Engelse taal.
to_tsvector(json(b))
vereist Postgres 10 of later.
Gerelateerd:
- Gedeeltelijke overeenkomst ophalen uit GIN-geïndexeerde TSVECTOR-kolom
- Patroon komt overeen met LIKE, VERGELIJKBAAR MET of reguliere expressies in PostgreSQL