返回Postgres嵌套的JSON数组

时间:2016-07-19 12:16:13

标签: json postgresql jsonb

我一直在寻找答案,但没有找到足够接近我所寻找的东西。

我有两张桌子:

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 db中返回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
    }]
}]

我能够从这里得到类似的东西[PostgreSQL and nodejs/pg, return nested JSON,但是除了技能名称之外我找不到任何东西。

1 个答案:

答案 0 :(得分:5)

表格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对象的元素顺序是未定义的。