如何从非JSONB postgres表中将数据作为嵌套JSONB加载

时间:2017-08-28 16:04:00

标签: postgresql jsonb

我试图从postgres后端构建一个对象供我使用。有问题的表看起来像这样:

我们有一些基本上充当矩阵的行,其中列是Field_Columns。 Field_Values是填充单元格。

Create Table Platform_User (
    serial id PRIMARY KEY
)

Create Table Things (
    serial id PRIMARY KEY,
    INTEGER user_id REFERENCES Platform_User(id)
)

Create Table Field_Columns (
    serial id PRIMARY KEY,
    TEXT name,
)

Create Table Field_Values (
    INTEGER field_column_id REFERENCES Field_Columns(id),
    INTEGER thing_id REFERENCES Things(id)
    TEXT content,
    PRIMARY_KEY(field_column_id, thing_id)
)

如果我尝试将单个Thing的Field_Values加载为JSON,这将很简单,如下所示:

SELECT JSONB_OBJECT(
    ARRAY(
        SELECT name
        FROM Field_Columns
        ORDER BY Field_Columns.id
    ),
    ARRAY(
        SELECT Field_Values.content
        FROM Fields_Columns
        LEFT JOIN Field_Values ON Field_Values.field_column_id = Field_Columns.id
            AND Field_Values.thing_id = Things.id
        ORDER BY Field_Columns.id)
    )
)
FROM Things
WHERE Thing.id = $1

但是,我想在返回时将JSON对象构造成这样。我想获得所有Fields的对象:Field_Values对象,用户拥有的东西

{
    14:
        {
            'first field':'asdf',
            'other field':''
        }
    25:
        {
            'first field':'qwer',
            'other field':'dfgdsfg'
        }
    43:
        {
            'first field':'',
            'other field':''
        }
}

我构建此查询的工作看起来像这样,但我遇到了JSONB对象函数不想构建一个对象的问题,其中字段的值是一个对象本身

SELECT (
    JSONB_OBJECT(
        ARRAY(SELECT Things.id::TEXT
            FROM Things
            WHERE Things.user_id = $2
            ORDER BY Things.id
        ),

        ARRAY(SELECT JSONB_OBJECT(
            ARRAY(
                SELECT name
                FROM Field_Columns
                ORDER BY Field_Columns.id),
            ARRAY(
                SELECT Field_Values.content
                FROM Field_Columns
                LEFT JOIN Field_Values ON Field_Values.field_column_Id = Field_Columns.id
                    AND Field_Values.thing_id = Things.id
                ORDER BY Field_Columns.id)
            )
            FROM Things
            WHERE Things.user_id = $2
            ORDER BY Things.id
        )
    )
) AS thing_fields

我得到的具体错误是函数jsonb_object(text [],jsonb [])不存在。有没有办法做到这一点,不涉及大量的文本转换和这样的废话?或者我只需要放弃尝试在查询中对数据进行排序,而是在我的代码中执行此操作。

1 个答案:

答案 0 :(得分:0)

你的DDL脚本在语法上是不正确的,所以我为你创建了这些:

create table platform_users (
    id int8 PRIMARY KEY
);
create table things (
    id int8 PRIMARY KEY,
    user_id int8 REFERENCES platform_users(id)
);
create table field_columns (
    id int8 PRIMARY KEY,
    name text
);
create table field_values (
    field_column_id int8 REFERENCES field_columns(id),
    thing_id int8 REFERENCES things(id),
    content text,
    PRIMARY KEY(field_column_id, thing_id)
);

我还创建了一些脚本来填充db:

insert into platform_users(id) values (1);
insert into platform_users(id) values (2);
insert into platform_users(id) values (3);
insert into platform_users(id) values (4);
insert into platform_users(id) values (5);

insert into things(id, user_id) values(1, 1);
insert into things(id, user_id) values(2, 1);
insert into things(id, user_id) values(3, 2);
insert into things(id, user_id) values(4, 2);

insert into field_columns(id, name) values(1, 'col1');

insert into field_columns(id, name) values(2, 'col2');

insert into field_values(field_column_id, thing_id, content) values(1, 1, 'thing1 val1');
insert into field_values(field_column_id, thing_id, content) values(2, 1, 'thing1 val2');
insert into field_values(field_column_id, thing_id, content) values(1, 2, 'thing2 val1');
insert into field_values(field_column_id, thing_id, content) values(2, 2, 'thing2 val2');

下次请求帮助时请包含此类脚本,并确保脚本正确无误。这将减少回答问题所需的工作。

您可以通过使用jsonb_object_agg

聚合键值对来获取您的jsonb值
select 
    t.id,
    jsonb_object_agg(fc.name, fv.content)
from 
    things t inner join
    field_values fv on fv.thing_id = t.id inner join
    field_columns fc on fv.field_column_id = fc.id
group by 1

结果如下:

thing_id;jsonb_value
1;"{"col1": "thing1 val1", "col2": "thing1 val2"}"
2;"{"col1": "thing2 val1", "col2": "thing2 val2"}"