【问题标题】:How to index jsonb integer values如何索引 jsonb 整数值
【发布时间】:2015-05-25 15:26:08
【问题描述】:

我正在尝试使用“新”JSONB 类型。

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

我试过了:

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

我从这篇帖子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

【问题讨论】:

    标签: postgresql indexing gwt-gin jsonb


    【解决方案1】:

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

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

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

    这是基于我的经验并查看了 Postgres 文档。

    【讨论】:

      【解决方案2】:

      您可以转换为整数并使用 contrib/btree_gin 扩展。

      创建扩展 btree_gin;
      使用 gin( cast (jb->>'price' as int)) 在 tt 上创建索引 tt_jb_int_idx;
      解释分析 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) (实际时间=0.016..0.016 rows=1 loops= 1)
               索引条件:((((jb ->> 'price'::text))::integer > 3) AND (((jb ->> 'price'::text))::integer 

      【讨论】:

        【解决方案3】:

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

        create index test1 on documents using gin (properties);
        

        【讨论】:

        • 谢谢——我想这就是我正在寻找的答案。即使文档没有指定它,您也可以使用此解决方案使用 CAST 来获取范围结果,如:`EXPLAIN ANALYZE SELECT COUNT(*) FROM documents WHERE cast(properties->>'publication_year' AS integer) > 2012 AND cast(properties->>'publication_year' AS integer)
        • 我不确定,如果以这种方式使用它会对性能产生影响(我猜这是目标)。根据文档 - 这种类型的索引不支持“->>”运算符。另外 - 您可以将 x > A AND x < B 组合成 x BETWEEN A AND B
        【解决方案4】:

        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';
        

        【讨论】:

        • 谢谢,这很有帮助,但它并没有解决我的主要问题:范围查询(也许我应该更明确一点)。最终目标是查找所有 publication_year 为 > 2012 和
        • @WillKessler 您可以使用 b 树索引来做到这一点。你试过了吗?
        • 我试过了,但没有得到正确的查询。但是现在有了您的帮助和 murison,我明白了,请参阅上面对 murison 回复的评论。不过,感谢您的帮助。
        猜你喜欢
        • 1970-01-01
        • 2021-10-19
        • 2018-08-27
        • 2017-09-11
        • 2018-05-13
        • 1970-01-01
        • 1970-01-01
        • 2019-03-21
        • 1970-01-01
        相关资源
        最近更新 更多