返回 Postgres 嵌套 JSON 数组

Returning Postgres Nested JSON Array

我一直在四处寻找这个问题的答案,但没有找到足够接近我所寻找的答案。

我有两个表:

CREATE TABLE skill_tree (
    ID SERIAL PRIMARY KEY,
    NAME TEXT NOT NULL,
    DESCRIPTION TEXT NOT NULL
);

CREATE TABLE skill (
    ID SERIAL PRIMARY KEY,
    NAME TEXT NOT NULL,
    DESCRIPTION TEXT NOT NULL,
    DURATION INTEGER NOT NULL,
    COOLDOWN INTEGER NOT NULL,
    SKILL_TREE_ID SERIAL REFERENCES skill_tree(id)
);

我正在尝试从我的 Postgres 数据库中 return JSON,其结构如下:

[{
    "id": 1,
    "name": "skill tree 1",
    "description": "skill tree description",
    "skills": [{
        "id": 1,
        "name": "skill 1",
        "description": "skill 1 desc",
        "duration": 10,
        "cooldown": 20
    }, {
        "id": 2,
        "name": "skill 2",
        "description": "skill 2 desc",
        "duration": 20,
        "cooldown": 30
    }]
}]

我能够从这里得到类似的东西 但除了技能名称之外无法检索到任何东西。

table skill 应该是这样的:

CREATE TABLE skill (
    ID SERIAL PRIMARY KEY,
    NAME TEXT NOT NULL,
    DESCRIPTION TEXT NOT NULL,
    DURATION INTEGER NOT NULL,
    COOLDOWN INTEGER NOT NULL,
    SKILL_TREE_ID INTEGER REFERENCES skill_tree(id) -- cannot be serial!
);

使用 jsonb_build_object()jsonb_agg()。请注意,查询在某种程度上类似于预期的对象。

select jsonb_pretty(jsonb_agg(js_object)) result
from (
    select 
        jsonb_build_object(
            'id', id, 
            'name', name, 
            'description', description, 
            'skills', jsonb_agg(skill)
        ) js_object
    from (
        select 
            t.*, 
            jsonb_build_object(
                'id', s.id, 
                'name', s.name, 
                'description', s.description, 
                'duration', duration, 
                'cooldown', cooldown
            ) skill
        from skill_tree t
        join skill s on s.skill_tree_id = t.id
        ) s
    group by id, name, description
    ) s;

我用 jsonb_pretty() 包装了结果以获得不错的输出:

                     result                      
-------------------------------------------------
 [                                              +
     {                                          +
         "id": 1,                               +
         "name": "skill tree 1",                +
         "skills": [                            +
             {                                  +
                 "id": 1,                       +
                 "name": "skill 1",             +
                 "cooldown": 20,                +
                 "duration": 10,                +
                 "description": "skill 1 desc"  +
             },                                 +
             {                                  +
                 "id": 2,                       +
                 "name": "skill 2",             +
                 "cooldown": 30,                +
                 "duration": 30,                +
                 "description": "skill 2 desc"  +
             }                                  +
         ],                                     +
         "description": "skill tree description"+
     }                                          +
 ]

请注意,json 对象的元素顺序未定义。