简体   繁体   English

在PostgreSQL 9.6中,扩展填充简单JSON dicts的JSONB列的最简单方法是什么?

[英]In PostgreSQL 9.6, what's the simplest way to expand a JSONB column filled with simple JSON dicts?

Say, I have a table json_table with a JSONB column, json_field . 说,我有一个带有JSONB列的表json_tablejson_field Each element in this column is a single uncomplicated dict, eg, 此列中的每个元素都是单个简单的dict,例如,

{'first_field': 2 , 'second_field': 42}

Is there a way to create a new table were the dicts are turned into columns? 有没有办法创建一个新的表,如果将dicts变成列?

My current approach is as follows: 我目前的做法如下:

CREATE TABLE normal_table ... first_field, second_field ... etc;
INSERT INTO normal_table (
    id,
    first_field,
    second_field,
    ...
)
SELECT
    id,
    json_field->>'first_field',
    json_field->>'second_field',
    ...
FROM json_table;

Is there a way to do something like the following? 有没有办法做以下的事情?

SELECT
    id,
    expand_json_dict(json_field)
FROM json_table;

Or a similar succinct way of doing it? 或者类似的简洁方式呢? The JSONB column has a lot of fields I want to expand, and the queries become unwieldy. JSONB列有很多我想要扩展的字段,查询变得难以处理。 I've actually made a Python function which generates create/insert scripts. 我实际上已经创建了一个生成创建/插入脚本的Python函数。 Still, I'd love for there to be a nice PostgreSQL way to do it. 尽管如此,我仍然希望有一个很好的PostgreSQL方法来做到这一点。

Any thoughts? 有什么想法吗?

Edit 编辑

The following is the working solution based on feedback here. 以下是基于反馈的工作解决方案。 Thanks guys. 多谢你们。

drop table if exists json_table;
create table json_table (
    id int,
    json_field jsonb
);
insert into json_table VALUES
    (2, ('{"second_field": 43, "first_field": 3}'::jsonb)),
    (1, ('{"first_field": 2 , "second_field": 42}'::jsonb));

drop table if exists normal_table;
create table normal_table (
    id int,
    first_field int,
    second_field int
);

insert into normal_table
select (
    jsonb_populate_record(
        null::normal_table,
        jsonb_set(json_field, '{id}', id::text::jsonb)
    )
).*
from json_table;

select * from normal_table;

Use the normal_table type as the base type to the jsonb_populate_record function: 使用normal_table类型作为jsonb_populate_record函数的基类型:

create table normal_table (
    id int,
    first_field int,
    second_field int
);

with json_table (json_field) as ( values
    ('{"first_field": 2 , "second_field": 42}'::jsonb)
)
select (jsonb_populate_record(null::normal_table, json_field)).*
from json_table
;
 id | first_field | second_field                                                                                                                                          
----+-------------+--------------                                                                                                                                         
    |           2 |           42

If it is necessary to generate the id to be inserted use jsonb_set : 如果有必要生成要插入的id ,请使用jsonb_set

with json_table (json_field) as ( values
    ('{"first_field": 2 , "second_field": 42}'::jsonb),
    ('{"first_field": 5 , "second_field": 1}')
)
select (
    jsonb_populate_record(
        null::normal_table,
        jsonb_set(json_field, '{id}', (row_number() over())::text::jsonb)
    )
).*
from json_table
;
 id | first_field | second_field 
----+-------------+--------------
  1 |           2 |           42
  2 |           5 |            1

You can create a type (record) that reflects your keys and then use json_populate_record : 您可以创建反映键的类型(记录),然后使用json_populate_record

create type my_type as (first_field varchar, second_field varchar);

SELECT id, (json_populate_record(null::my_type, json_field)).*
FROM json_table;

If there are keys in the JSON document that are not present in the type, they are simply ignored. 如果JSON文档中的键不存在于类型中,则会忽略它们。 If there are fields in the type definition that don't have a match in the JSON document they will be null . 如果类型定义中的字段在JSON文档中没有匹配项,则它们将为null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM