【问题标题】:How to load data as nested JSONB from non-JSONB postgres tables如何从非 JSONB postgres 表中将数据加载为嵌套 JSONB
【发布时间】:2018-02-05 23:11:29
【问题描述】:

我正在尝试从我的 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)
)

如果我尝试将单个事物的 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[]) 不存在。有没有办法做到这一点,不涉及大量的文本转换和这样的废话?或者我是否只需要放弃尝试在查询中对我的数据进行排序,而是在我的代码中进行。

【问题讨论】:

    标签: postgresql jsonb


    【解决方案1】:

    您的 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)
    );
    

    我还创建了一些脚本来填充数据库:

    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"}"
    

    【讨论】:

      猜你喜欢
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多