2015-03-22 19 views
9

Tôi đang cố sử dụng loại JSONB "mới mẻ".Cách lập chỉ mục các giá trị số nguyên jsonb

Tôi có một bảng documents với trường là properties jsonb và trong đó là trường publication_year. Tôi muốn tìm tất cả hồ sơ tài liệu trong phạm vi năm, ví dụ: 2013-2015. [EDIT: Việc truy vấn một loạt các giá trị là thách thức chính ở đây, mặc dù tôi đã sử dụng ví dụ đối sánh chính xác bên dưới. Cách tiếp cận yêu cầu cũng sẽ được áp dụng cho, nói dãy đô la (giá> $ 20 và giá < $ 40) hoặc dãy timestamp)]

Tôi đã thử:.

create index test1 on documents using gin ((cast(properties->'announced_on_year' as integer))); 

ERROR: cannot cast type jsonb to integer 

cũng như:

create index test1 on documents using gin (cast(properties->>'publication_year' as integer)); 

ERROR: data type integer has no default operator class for access method "gin" 
HINT: You must specify an operator class for the index or define a default operator class for the data type.` 

Tôi thấy từ bài đăng này http://www.postgresql.org/message-id/[email protected] rằng điều này sẽ có thể, nhưng tôi không thể tìm ra cú pháp đúng.

Khi tôi chỉ làm một chỉ số đơn giản:

create index test1 on documents using gin ((properties->'publication_year')); 

một chỉ số được tạo ra, nhưng tôi không thể truy vấn nó sử dụng các giá trị số nguyên để có được một phạm vi đi, nó nói

select count(*) from documents where properties->>'publication_year' = 2015; 
ERROR: operator does not exist: text = integer 
LINE 1: ...*) from documents where properties->>'publication_year' = 2015; 
          ^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. 

Bất cứ lời khuyên và gợi ý đánh giá cao. Tôi chắc rằng những người khác cũng sẽ được hưởng lợi. TIA

Trả lời

1

Tại sao bạn không xác định một chỉ số cho toàn bộ jsonb , as described in the doc?

create index test1 on documents using gin (properties); 
+0

Cảm ơn bạn-- Tôi nghĩ đây là câu trả lời tôi đang tìm kiếm. Mặc dù các tài liệu không chỉ định nó, bạn có thể với giải pháp này sử dụng CAST để có được kết quả phạm vi, như: 'GIẢI THÍCH ANALYZE SELECT COUNT (*) TỪ tài liệu WHERE cast (properties - >> 'publication_year' AS integer)> 2012 VÀ đúc (thuộc tính - >> 'publication_year' AS số nguyên) <2016; –

+0

Tôi không chắc chắn, nếu sử dụng nó theo cách này sẽ có tác động đến hiệu suất (mà tôi đoán là mục tiêu). Theo tài liệu - toán tử "- >>" không được loại chỉ mục này hỗ trợ. Ngoài ra - bạn có thể kết hợp 'x> A VÀ x murison

2

1) Không có chỉ mục GIN cho số nguyên (ít nhất là không nằm ngoài hộp), hãy sử dụng btree.

create index test1 on documents using btree (cast (properties->>'announced_on_year' as int)); 

2) Lỗi này là khá tự giải thích, đúc số nguyên dưới dạng văn bản hoặc sử dụng văn bản cho việc so sánh:

select count(*) from documents where properties->>'publication_year' = '2015'; 
+0

Cảm ơn bạn, điều đó rất hữu ích, nhưng nó không giải quyết được vấn đề chính của tôi: truy vấn phạm vi (có lẽ tôi nên rõ ràng hơn). Mục tiêu cuối cùng giống như tìm tất cả các bản ghi trong đó 'publication_year' là> 2012 và <2016. –

+0

@WillKessler Bạn có thể làm điều đó với chỉ mục b-tree. Bạn đã thử chưa –

+0

Tôi đã thử, nhưng không nhận được quyền truy vấn. Nhưng bây giờ với sự giúp đỡ của bạn và murison, tôi đã có nó, xem bình luận ở trên để phản ứng của murison. Cảm ơn bạn đã hỗ trợ của bạn tuy nhiên. –

1

Bạn có thể truyền dưới dạng số nguyên và sử dụng phần mở rộng contrib/btree_gin.

create extension btree_gin; 
create index tt_jb_int_idx on tt using gin(cast (jb->>'price' as int)); 
explain analyze select * from tt where cast(jb->>'price' as int) > 3 and cast(jb->>'price' as int) > 'price'::text))::integer > 3) AND (((jb ->> 'price'::text))::integer Bitmap Index Scan on tt_jb_int_idx (cost=0.00..28.06 rows=6 width=0) (actual time=0.016..0.016 rows=1 loops=1) 
     Index Cond: ((((jb ->> 'price'::text))::integer > 3) AND (((jb ->> 'price'::text))::integer
2

Tôi đã tìm thấy trong kinh nghiệm của mình rằng việc sử dụng chỉ mục GIN trên cột JSONB không nhanh hơn. Bạn chỉ có thể tạo ra một chỉ số bình thường bằng cách đúc nó vào một số nguyên

CREATE INDEX test1 ON documents ((properties->>'publication_year')::int); 

Ngoài ra, có một số GIN limitations mà cần được xem xét trước khi tạo một. Ngay cả việc lập chỉ mục toàn bộ cột JSONB cũng có thể dẫn đến các chỉ mục có kích thước bảng lớn.

Điều này dựa trên kinh nghiệm của tôi và xem qua tài liệu Postgres.

Các vấn đề liên quan