查询JSON类型中的数组元素

时间:2014-03-29 20:50:26

标签: sql json postgresql jsonb lateral

我正试图在PostgreSQL 9.3中测试json类型 我在名为json的表格中有一个名为data的{​​{1}}列。 JSON看起来像这样:

reports

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

的查询
"background"

但是由于SELECT data AS data FROM reports where data->>'background' = 'background.png' 有一个值数组,我似乎无法写出有效的东西。是否可以在数据库中查询与"objects"匹配的所有报告?我查看了这些来源,但仍然无法得到它:

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

'src' = 'foo.png'

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

3 个答案:

答案 0 :(得分:156)

Postgres 9.3 + 中的

json

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

WITH reports(data) AS (
   VALUES ('{"objects":[{"src":"foo.png"}, {"src":"bar.png"}]
           , "background":"background.png"}'::json)
   ) 
SELECT *
FROM   reports r, json_array_elements(r.data#>'{objects}') obj
WHERE  obj->>'src' = 'foo.png';

CTEWITH查询)只能替换表reports
或者,等效于级别的嵌套:

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

->>, -> and #> operators are explained in the manual.

两个查询都使用隐式JOIN LATERAL

SQL Fiddle.

密切相关的答案:

Postgres 9.4 +

中的

jsonb

使用等效的jsonb_array_elements()

更好,使用新的"包含"运算符@>(最好与表达式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 数组,我们需要匹配搜索项中的结构并将数组元素包装到方括号中。搜索普通记录时删除数组括号。

详细说明和更多选项:

答案 1 :(得分:3)

创建一个列为json类型的表

ID

现在让我们插入json数据

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

现在让我们进行一些查询以获取数据

# 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)

即可检索值。
->>

答案 2 :(得分:1)

从表中选择data->'objects'-> 0->'src'作为SRC,其中data->'objects'-> 0->'src'='foo.png'