繁体   English   中英

扩展存储在 JSONB 中的对象数组

[英]Expanding an array of objects stored in JSONB

我有一个表,其中包含一个 JSONB 字段和一个 JSON 数组,我想扩展一个简单的格式。 这是表格定义的精简版:

CREATE TABLE IF NOT EXISTS data.data_file_info (
    id uuid NOT NULL,
    server_name_ citext NOT NULL,
    table_stats jsonb DEFAULT '{}'::jsonb NOT NULL,
    PRIMARY KEY(id)
);

下面是来自 table_stats JSONB 字段的一些示例数据:

[
    {"table_name":"AutoReportOrg","record_count":48,"table_number":167},
    {"table_name":"AutoReportOrgAudit","record_count":0,"table_number":170},
    {"table_name":"AutoReportOrgRecipient","record_count":126,"table_number":168},
    {"table_name":"AutoReportRecipient","record_count":28,"table_number":169}
]

json_populate_recordset和/或json_to_recordset函数似乎应该是我所追求的,但我无法让它们工作。 我查看了很多过去的问题,并尝试了各种语法。 以下是我得到的印象应该有效......但事实并非如此:

-- Define a custom type to act as a template for the JSON parser.
DROP TYPE IF EXISTS dfits;
CREATE TYPE api.dfits AS (
    table_name citext,
    record_count int8,
    table_number int4);

-- And now we parse!
SELECT server_name_, (json_populate_recordset(null::dfits, table_stats)).* FROM data_file_info;

但我得到了这个:

ERROR:  function json_populate_recordset(dfits, jsonb) does not exist
LINE 4: SELECT server_name_, (json_populate_recordset(null::dfits, t...
                              ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts. (Line 9)

谁能发现我的设置中的错误? 似乎我得到了正确的部分,但我没有设法将它们正确地组合在一起。

Postgres 11.4,部署在 RDS 上。

跟进

GMB 回答了我的问题,但我想在这里为档案添加更多内容。 经过我的输入错误(JSON 而不是 JSONB),这些东西的关键似乎是 Postgres 需要一个模板/映射来定义 JSON/JSONB 数组中元素的结构。 我认为在这种情况下,输入数据可以来自四个(?)地方:

  • 现有的表定义,因为每个表都是一种类型。
  • 现有视图定义,因为每个视图都是一种类型。 (您可以在pg_class以及基表派生类型中找到它们。
  • 使用CREATE TYPE创建的自定义类型,就像我上面使用的一样。
  • 内联声明。

为了比较,这是一个使用上面显示的自定义类型dfits的更新查询:

SELECT server_name_, expanded_json.*
FROM
   data_file_info, 
   jsonb_populate_recordset(null::dfits, table_stats) as expanded_json

现在这是另一个使用内联声明的版本:

SELECT server_name_, expanded_json.*
FROM
   data_file_info, 
    jsonb_to_recordset(table_stats) as expanded_json 
        (table_name text, record_count int, table_number int)

我可以看到这两种方法的用途。 但是,话虽如此, CREATE TYPE还是非常棒的。 您可以将它与CREATE CAST结合使用,以生成非常紧凑且易于使用的代码。

由于您使用的是jsonb列,因此您实际上需要jsonb_populate_recordset 还有,这个function返回的是一组记录,所以需要放在FROM子句中,而不是SELECT子句中。

考虑:

SELECT server_name, x.*
FROM
   data_file_info, 
   jsonb_populate_recordset(null::dfits, table_stats) x

DB Fiddle 上的演示

| server_name | table_name             | record_count | table_number |
| ----------- | ---------------------- | ------------ | ------------ |
| foo         | AutoReportOrg          | 48           | 167          |
| foo         | AutoReportOrgAudit     | 0            | 170          |
| foo         | AutoReportOrgRecipient | 126          | 168          |
| foo         | AutoReportRecipient    | 28           | 169          |

暂无
暂无

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

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