SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Verwandte, mit Erklärung:
- Durchsuchen Sie ein JSON-Array nach einem Objekt, das einen Wert enthält, der einem Muster entspricht
Oder einfacher mit dem @?
Operator seit Postgres 12 SQL/JSON implementiert:
SELECT *
-- optional to show the matching item:
-- , jsonb_path_query_first(tags, '$[*] ? (@ like_regex "^ tag" flag "i")')
FROM posts
WHERE tags @? '$[*] ? (@ like_regex "TAG")';
Der Operator @?
ist nur ein Wrapper um die Funktion jsonb_path_exists()
. Das ist also äquivalent:
...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Keiner hat Indexunterstützung. (Kann für @?
hinzugefügt werden Operator später, aber noch nicht auf Seite 13). Daher sind diese Abfragen für große Tabellen langsam. Besser wäre ein normalisiertes Design, wie Laurenz es bereits vorgeschlagen hat - mit einem Trigram-Index:
- Änderungen der PostgreSQL LIKE-Abfrageleistung
Nur für den Präfixabgleich (LIKE 'TAG%'
, kein führender Platzhalter), könnten Sie es mit einem Volltextindex zum Laufen bringen :
CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
Und eine passende Abfrage:
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Oder verwenden Sie das english
Wörterbuch statt simple
(oder was auch immer zu Ihrem Fall passt), wenn Sie die Wortstammbildung für die natürliche englische Sprache wünschen.
to_tsvector(json(b))
erfordert Postgres 10 oder später.
Verwandte:
- Teilweise Übereinstimmung aus GIN-indizierter TSVECTOR-Spalte abrufen
- Mustervergleich mit LIKE, SIMILAR TO oder regulären Ausdrücken in PostgreSQL