Câu trả lời gốc sau đây chỉ áp dụng cho Postgres 9.3. Để có câu trả lời Postgres 9.4, hãy xem Cập nhật bên dưới.
Điều này được xây dựng dựa trên câu trả lời được tham khảo của Erwin , nhưng rõ ràng hơn một chút cho câu hỏi này.
Các ID trong trường hợp này là bigint
s, vì vậy hãy tạo một hàm trợ giúp để chuyển đổi một mảng JSON thành một Postgres bigint
mảng:
CREATE OR REPLACE FUNCTION json_array_bigint(_j json)
RETURNS bigint[] AS
$$
SELECT array_agg(elem::text::bigint)
FROM json_array_elements(_j) AS elem
$$
LANGUAGE sql IMMUTABLE;
Chúng tôi có thể dễ dàng (và có lẽ còn hữu dụng hơn) trả về một văn bản
mảng ở đây để thay thế. Tôi nghi ngờ việc lập chỉ mục trên bigint
nhanh hơn nhiều so với text
nhưng tôi đang gặp khó khăn trong việc tìm kiếm bằng chứng trực tuyến để sao lưu điều đó.
Để xây dựng chỉ mục:
CREATE INDEX "myindex" ON "mytable"
USING GIN (json_array_bigint("blob"->'ids'));
Đối với truy vấn, điều này hoạt động và sử dụng chỉ mục:
SELECT * FROM "mytable"
WHERE '{185603363289694211}' <@ json_array_bigint("blob"->'ids');
Làm điều này cũng sẽ hoạt động để truy vấn, nhưng nó không sử dụng chỉ mục:
SELECT * FROM "mytable"
WHERE 185603363289694211 = ANY(json_array_bigint("blob"->'ids'));
Cập nhật cho 9.4
Postgres 9.4 đã giới thiệu jsonb
loại hình. Đây là câu trả lời SO hay về jsonb và khi nào bạn nên sử dụng nó trên
. Tóm lại, nếu bạn đang truy vấn JSON, bạn nên sử dụng json
jsonb
.
Nếu bạn tạo cột của mình dưới dạng jsonb
, bạn có thể sử dụng truy vấn này:
SELECT * FROM "mytable"
WHERE blob @> '{"ids": [185603363289694211]}';
@>
là toán tử Postgres 'chứa, được lập thành tài liệu cho jsonb
tại đây
.Cảm ơn câu trả lời của Alain
vì đã làm cho tôi chú ý đến điều này.