如何从PostgreSQL中的jsonb数组获取特定对象?


16

我有一个名为“用户”的字段,其中包含一个大致如下所示的json数组:

"user"

[{ "_id" : "1", "count" : "4" }, { "_id" : "3", "count": "4"}]

现在我想要一个查询:

select count from tablename where id = "1"

我无法count从PostgreSQL 9.4中的json对象数组中获取特定字段。

Answers:


17

将您的值存储在规范化架构中会更加有效。也就是说,您还可以使其与当前设置一起使用。

假设条件

假设此表定义:

CREATE TABLE tbl (tbl_id int, usr jsonb);

“用户”是保留字,需要使用双引号作为列名。不要那样做 我usr改用。

询问

查询看起来不像(现在已删除的)注释那么简单:

SELECT t.tbl_id, obj.val->>'count' AS count
FROM   tbl t
JOIN   LATERAL jsonb_array_elements(t.usr) obj(val) ON obj.val->>'_id' = '1'
WHERE  t.usr @> '[{"_id":"1"}]';

3个基本步骤

1.便宜地识别合格行

WHERE t.usr @> '[{"_id":"1"}]'标识JSON数组中具有匹配对象的行。表达式可以在jsonb列上使用通用GIN索引,也可以在更专门的运算符类中使用jsonb_path_ops

CREATE INDEX tbl_usr_gin_idx ON tbl USING gin (usr jsonb_path_ops);

所添加的WHERE子句在逻辑上多余的,但是使用索引是必需的。join子句中的表达式强制执行相同的条件,但仅取消到目前为止已限定的每一行中的数组之后。有了索引支持,Postgres仅处理包含合格对象的行。小表无关紧要,与大表和仅有少数合格行的表有很大不同。

有关:

2.确定数组中的匹配对象

巢状jsonb_array_elements()。(unnest()仅适用于Postgres数组类型。)由于我们只对实际匹配的对象感兴趣,因此请立即过滤联接条件。

有关:

3.提取嵌套键的值 'count'

提取合格对象后,只需:obj.val->>'count'


2
哪里obj(value)来的?是在LATERAL JOINjsonb_array_elements还是其他位置?
泰勒·德威特

看来格式可能搞砸了。我是否正确地阅读了JOIN LATERAL jsonb_array_elements(t.usr) obj(value) is short for JOIN LATERAL jsonb_array_elements(t.usr) AS obj(value)obj(value)是表和列的别名?在此示例中,如果obj是表别名,那么别名是什么?该集合从jsonb_array_elements
泰勒·德威特

1
是的,是的。我删除了我的混乱评论。
欧文·布兰德斯特

是否需要使用列别名?在我的测试中,JOIN LATERAL jsonb_array_elements(t.usr) obj ON obj->>'_id' = '1'具有相同的效果(一旦您更新了select语句以使用value而不是val)。似乎jsonb_array_elements(t.usr)返回的表只有一个列。postgres聪明并且意识到与之obj ->>相同obj.val ->>吗?
泰勒·德威特

只有一列,Postgres使用给定的别名作为表列的名称。我只是明确地说,因为有许多返回返回多个列的集合返回函数。
Erwin Brandstetter,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.