我正试图在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专家,所以我不知道我做错了什么。
答案 0 :(得分:156)
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';
CTE(WITH
查询)只能替换表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
。
密切相关的答案:
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'