如何更深层次查询PostgreSQL嵌套JSONB?

kta*_*lez 5 postgresql jsonb postgresql-9.4

我是 JSON/JSONB 数据类型的新手,在从更深层次选择 JSONB 元素时遇到一些问题。

这是一个示例表:

CREATE TABLE person (id integer, details jsonb);

INSERT INTO person (id, details) VALUES
("id": 1, {"favorites":{"colors":"blue", "colors":"red"}}),
("id": 2),
("id": 3, {"favorites":{"colors":"blue", "colors":"red", "colors":"green"}});
Run Code Online (Sandbox Code Playgroud)


我想选择所有 p.details ->'favorites' ->>'colors',例如:

------------------------ 
| id | Favorite colors |
------------------------ 
| 1  | blue            |
------------------------ 
| 1  | red             |
------------------------ 
| 3  | blue            |
------------------------ 
| 3  | red             |
------------------------ 
| 3  | green           |
------------------------
Run Code Online (Sandbox Code Playgroud)


以下(或类似)给出了最喜欢的颜色的空列(也尝试使用 jsonb_array_elements):

SELECT p.id, p.details ->'favorites' ->>'colors' AS "Favorite colors"
FROM "person" p;

SELECT p.id, json_array_elements((p.details ->'favorites' ->>'colors')::json) AS "Favorite colors"
FROM "person" p;
Run Code Online (Sandbox Code Playgroud)


以下适用于简单的查询,但在检索更多数据时会使浏览器崩溃(最终用户在 Web 浏览器中使用查询)。

SELECT p.id, ((json_array_elements((json_array_elements(p.details::json)::json->>'favorites')::json))::json->>'colors') AS "Favorite colors"
    FROM "person" p;
Run Code Online (Sandbox Code Playgroud)

看来浏览器正在消耗大量内存。我发现一些帖子说多次调用 json_array_elements 会减慢查询速度: https: //www.postgresql.org/message-id/52EEEC37.9040305@2ndquadrant.com

对此有什么建议吗?

Dmi*_*kin 3

您提供的sql查询存在一些语法错误。如果我正确地猜测了数据库模式,那么它们应该如下所示:

DROP TABLE person;
CREATE TABLE person (id integer, details jsonb);

INSERT INTO person (id, details) VALUES
(1, '{"favorites":[{"colors":"blue"}, {"colors":"red"}]}'::jsonb),
(2, '{}'::jsonb),
(3, '{"favorites":[{"colors":"blue"}, {"colors":"red"}, {"colors":"green"}]}'::jsonb);
Run Code Online (Sandbox Code Playgroud)

如果这是正确的,那么您可以通过以下方式获得结果:

select id, jsonb_array_elements(details->'favorites')->'colors' from person
Run Code Online (Sandbox Code Playgroud)