如何索引 jsonb 整数值

How to index jsonb integer values

我正在尝试使用 "newish" JSONB 类型。

我有一个 documents table 和一个 properties jsonb 字段,其中有一个字段 publication_year。我想查找一年范围内的所有文档记录,例如2013-2015。 [编辑:查询一系列值是这里的主要挑战,即使我在下面使用了完全匹配示例。所请求的方法也适用于美元范围(价格 > 20 美元且价格 < 40 美元)或时间戳范围)。]

我试过:

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

ERROR:  cannot cast type jsonb to integer

以及:

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.`

我从这个 post http://www.postgresql.org/message-id/10736.1409063604@sss.pgh.pa.us 看到这应该是可能的,但我想不出正确的语法。

当我直接做索引时:

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

索引已创建,但我无法使用整数值查询它以获取范围,它说

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.

非常感谢任何提示和提示。我相信其他人也会受益。 TIA

1) 整数没有 GIN 索引(至少不是现成的),使用 btree。

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

2) 错误不言自明,将整数转换为文本或使用文本进行比较:

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

为什么不为整个 jsonb 字段定义一个索引,as described in the doc

create index test1 on documents using gin (properties);

您可以转换为整数并使用 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 

根据我的经验,我发现在 JSONB 列上使用 GIN 索引并不更快。您可以通过将其转换为整数来创建普通索引

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

此外,GIN 有一些 limitations 在创建 GIN 之前应该考虑的问题。即使索引整个 JSONB 列也会产生大量 table 大小的索引。

这是基于我的经验和对 Postgres 文档的查阅。