SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Relaterat, med förklaring:
- Sök i en JSON-array efter ett objekt som innehåller ett värde som matchar ett mönster
Eller enklare med @?
operatör sedan Postgres 12 implementerade 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 @?
är bara ett omslag runt funktionen jsonb_path_exists()
. Så detta är likvärdigt:
...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Inte heller har indexstöd. (Kan läggas till för @?
operatör senare, men inte där på sidan 13 ännu). Så dessa frågor är långsamma för stora bord. En normaliserad design, som Laurenz redan föreslagit skulle vara överlägsen - med ett trigramindex:
- PostgreSQL LIKE frågeprestandavariationer
För bara prefixmatchning (LIKE 'TAG%'
, inget inledande jokertecken), kan du få det att fungera med ett fulltextindex :
CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
Och en matchande fråga:
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Eller använd english
ordbok istället för simple
(eller vad som helst som passar ditt fall) om du vill ha härkomst för naturligt engelska språk.
to_tsvector(json(b))
kräver Postgres 10 eller senare.
Relaterat:
- Få partiell matchning från GIN-indexerad TSVECTOR-kolumn
- Mönstermatchning med LIKE, SIMILAR TO eller reguljära uttryck i PostgreSQL