查询 JSON 类型内的数组元素

Posted

技术标签:

【中文标题】查询 JSON 类型内的数组元素【英文标题】:Query for array elements inside JSON type 【发布时间】:2014-05-09 07:49:52 【问题描述】:

我正在尝试在 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' 匹配的所有报告?我已经查看了这些来源,但仍然无法得到它:

http://www.postgresql.org/docs/9.3/static/functions-json.html How do I query using fields inside the new PostgreSQL JSON datatype? http://michael.otacoo.com/postgresql-2/postgres-9-3-feature-highlight-json-operators/

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

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

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

【问题讨论】:

【参考方案1】:

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 数组,我们需要匹配搜索词中的结构并将数组元素也包裹在方括号中。搜索普通记录时删除数组括号。

更多解释和选项:

Index for finding an element in a JSON array

json 在 Postgres 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小提琴here旧sqlfiddle

或者,仅相当于单层的嵌套:

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

密切相关:

Query for element of array in JSON column

【讨论】:

@pacothelovetaco:为jsonb / pg 9.4 添加了更新。另外:对于简单的情况(1 级嵌套),-> 运算符也可以在第 9.3 页中为json 解决问题。 @pacothelovetaco,对于 pg 9.3,'#>' 不是秘诀,'->' 对你的情况来说很好,因为它也返回 json 对象。 '#>' 在嵌套 json 路径的情况下会更有帮助,因为它允许您轻松地在 '' 中指定路径 @> '["src":"foo.png"]';在 where 条件下工作正常但如何删除这样的特定对象?我不知道这个对象的索引。我想按键值删除。 @PranaySoni:请以 question 形式提出新问题。评论不是地方。您可以随时链接到这个以获取上下文。 亲爱的@ErwinBrandstetter,是否可以通过部分匹配找到两个文档?例如,我想获得两个记录类似 '["src":".png"]'【参考方案2】:

创建一个列类型为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';

【讨论】:

我发现这很有用。显示如何在 jsonb 中钻取数组 发现了很多复杂的方法,但这就是如此简单易懂!

以上是关于查询 JSON 类型内的数组元素的主要内容,如果未能解决你的问题,请参考以下文章

查询 JSON 列中的数组元素

mysql 5.7 json 类型 json 数组类型 普通字符串类型 10w数据 查询速度差异

如何从 Oracle JSON CLOB 类型的 JSON 数组中选择特定元素

php怎么将mysql查询的数组中 的(数字)字符串类型转为数字类型

MySQL数据类型 - JSON数据类型

选择数组内的嵌套 Typescript 类型泛型