SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Powiązane, z wyjaśnieniem:
- Wyszukaj w tablicy JSON obiekt zawierający wartość pasującą do wzorca
Lub prościej z @?
operator od czasu wdrożenia Postgres 12 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")';
Operator @?
jest tylko opakowaniem wokół funkcji jsonb_path_exists()
. Więc to jest równoważne:
...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Nie ma obsługi indeksu. (Może być dodany do @?
operatora później, ale jeszcze nie ma na stronie 13). Więc te zapytania są powolne w przypadku dużych tabel. Znormalizowany projekt, jak już sugerował Laurenz, byłby lepszy - z indeksem trygramu:
- Odmiany wydajności zapytań PostgreSQL LIKE
Wystarczy dopasować prefiks (LIKE 'TAG%'
, bez wiodącego symbolu wieloznacznego), możesz sprawić, by działał z indeksem pełnotekstowym :
CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
I pasujące zapytanie:
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Lub użyj english
słownik zamiast simple
(lub cokolwiek pasuje do twojego przypadku), jeśli chcesz rdzennie dla naturalnego języka angielskiego.
to_tsvector(json(b))
wymaga Postgres 10 lub później.
Powiązane:
- Pobierz częściowe dopasowanie z kolumny TSVECTOR indeksowanej GIN
- Dopasowywanie wzorców za pomocą LIKE, SIMILAR TO lub wyrażeń regularnych w PostgreSQL