我有一个名为“用户”的字段,其中包含一个大致如下所示的json数组:
"user"
:
[{ "_id" : "1", "count" : "4" }, { "_id" : "3", "count": "4"}]
现在我想要一个查询:
select count from tablename where id = "1"
我无法count
从PostgreSQL 9.4中的json对象数组中获取特定字段。
我有一个名为“用户”的字段,其中包含一个大致如下所示的json数组:
"user"
:
[{ "_id" : "1", "count" : "4" }, { "_id" : "3", "count": "4"}]
现在我想要一个查询:
select count from tablename where id = "1"
我无法count
从PostgreSQL 9.4中的json对象数组中获取特定字段。
Answers:
将您的值存储在规范化架构中会更加有效。也就是说,您还可以使其与当前设置一起使用。
假设此表定义:
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个基本步骤:
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仅处理包含合格对象的行。小表无关紧要,与大表和仅有少数合格行的表有很大不同。
有关:
巢状jsonb_array_elements()
。(unnest()
仅适用于Postgres数组类型。)由于我们只对实际匹配的对象感兴趣,因此请立即过滤联接条件。
有关:
'count'
提取合格对象后,只需:obj.val->>'count'
。
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
?
JOIN LATERAL jsonb_array_elements(t.usr) obj ON obj->>'_id' = '1'
具有相同的效果(一旦您更新了select语句以使用value
而不是val
)。似乎jsonb_array_elements(t.usr)
返回的表只有一个列。postgres聪明并且意识到与之obj ->>
相同obj.val ->>
吗?
obj(value)
来的?是在LATERAL JOIN
,jsonb_array_elements
还是其他位置?