SELECT *
FROM posts p
WHERE EXISTS (
SELECT FROM jsonb_array_elements_text(p.tags) tag
WHERE tag LIKE '%TAG%'
);
Có liên quan, có giải thích:
- Tìm kiếm một mảng JSON để tìm một đối tượng có chứa giá trị khớp với một mẫu
Hoặc đơn giản hơn với @?
toán tử kể từ khi Postgres 12 triển khai 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")';
Toán tử @?
chỉ là một trình bao bọc xung quanh hàm jsonb_path_exists()
. Vì vậy, điều này tương đương:
...
WHERE jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');
Không có hỗ trợ chỉ mục. (Có thể được thêm vào cho @?
sau đó, nhưng chưa có trong trang 13). Vì vậy, những truy vấn chậm đối với các bảng lớn. Một thiết kế chuẩn hóa, như Laurenz đã đề xuất sẽ tốt hơn - với chỉ số bát quái:
- Các biến thể hiệu suất truy vấn LIKE của PostgreSQL
Chỉ đối với đối sánh tiền tố (LIKE 'TAG%'
, không có ký tự đại diện đứng đầu), bạn có thể làm cho nó hoạt động với chỉ mục văn bản đầy đủ :
CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));
Và một truy vấn phù hợp:
SELECT *
FROM posts p
WHERE to_tsvector('simple', tags) @@ 'TAG:*'::tsquery
Hoặc sử dụng english
từ điển thay vì simple
(hoặc bất cứ điều gì phù hợp với trường hợp của bạn) nếu bạn muốn sử dụng ngôn ngữ tiếng Anh tự nhiên.
to_tsvector(json(b))
yêu cầu Postgres 10 trở lên.
Có liên quan:
- Nhận đối sánh từng phần từ cột TSVECTOR được lập chỉ mục GIN
- Đối sánh mẫu với LIKE, SIMILAR TO hoặc biểu thức chính quy trong PostgreSQL