繁体   English   中英

查询 JSON 类型内的数组元素

[英]Query for array elements inside JSON type

我正在尝试测试 PostgreSQL 9.3 中的json类型。
我在名为reports的表中有一个名为datajson列。 JSON 看起来像这样:

{
  "objects": [
    {"src":"foo.png"},
    {"src":"bar.png"}
  ],
  "background":"background.png"
}

我想在表中查询与 'objects' 数组中的 'src' 值匹配的所有报告。 例如,是否可以在数据库中查询匹配'src' = 'foo.png'所有报告? 我成功地编写了一个可以匹配"background"的查询:

SELECT data AS data FROM reports where data->>'background' = 'background.png'

但是由于"objects"有一个值数组,我似乎无法写出有效的东西。 是否可以在数据库中查询所有匹配'src' = 'foo.png' 我已经查看了这些来源,但仍然无法获得:

我也试过这样的事情,但无济于事:

SELECT json_array_elements(data->'objects') AS data from reports
WHERE  data->>'src' = 'foo.png';

我不是 SQL 专家,所以我不知道我做错了什么。

jsonb Postgres里9.4+

可以使用与下面相同的查询,只需使用jsonb_array_elements()

而是将jsonb “包含”运算符@>与表达式data->'objects'上的匹配 GIN 索引结合使用:

CREATE INDEX reports_data_gin_idx ON reports
USING gin ((data->'objects') jsonb_path_ops);

SELECT * FROM reports WHERE data->'objects' @> '[{"src":"foo.png"}]';

由于键objects包含一个 JSON数组,我们需要匹配搜索词中的结构并将数组元素也包装在方括号中。 搜索普通记录时删除数组括号。

更多解释和选项:

Postgres 中的json 9.3+

FROM子句的横向连接中使用函数json_array_elements()取消嵌套 JSON 数组并测试其元素:

SELECT data::text, obj
FROM   reports r, json_array_elements(r.data#>'{objects}') obj
WHERE  obj->>'src' = 'foo.png';

db<> 在这里摆弄
旧的sqlfiddle

或者,等效嵌套的只是一个单一的水平:

SELECT *
FROM   reports r, json_array_elements(r.data->'objects') obj
WHERE  obj->>'src' = 'foo.png';

->>->#>运算符在手册中进行了解释。

这两个查询都使用隐式JOIN LATERAL

密切相关:

创建一个列为 json 类型的表

CREATE TABLE friends ( id serial primary key, data jsonb);

现在让我们插入json数据

INSERT INTO friends(data) VALUES ('{"name": "Arya", "work": ["Improvements", "Office"], "available": true}');
INSERT INTO friends(data) VALUES ('{"name": "Tim Cook", "work": ["Cook", "ceo", "Play"], "uses": ["baseball", "laptop"], "available": false}');

现在让我们做一些查询来获取数据

select data->'name' from friends;
select data->'name' as name, data->'work' as work from friends;

您可能已经注意到结果带有引号 (") 和括号 ([])

    name    |            work            
------------+----------------------------
 "Arya"     | ["Improvements", "Office"]
 "Tim Cook" | ["Cook", "ceo", "Play"]
(2 rows)

现在只检索值只需使用->>

select data->>'name' as name, data->'work'->>0 as work from friends;
select data->>'name' as name, data->'work'->>0 as work from friends where data->>'name'='Arya';

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM