在 PostgreSQL 9.5+ 中追加(推送)和从 JSON 数组中删除

Posted

技术标签:

【中文标题】在 PostgreSQL 9.5+ 中追加(推送)和从 JSON 数组中删除【英文标题】:Appending (pushing) and removing from a JSON array in PostgreSQL 9.5+ 【发布时间】:2017-07-03 04:17:52 【问题描述】:

For versions less than 9.5 see this question

我已经使用这个在 PostgreSQL 中创建了一个表:

CREATE TEMP TABLE jsontesting
AS
  SELECT id, jsondata::jsonb FROM ( VALUES
    (1, '["abra","value","mango", "apple", "sample"]'),
    (2, '["japan","china","india", "russia", "australia"]'),
    (3, '["must", "match"]'),
    (4, '["abra","value","true", "apple", "sample"]'),
    (5, '["abra","false","mango", "apple", "sample"]'),
    (6, '["string","value","mango", "apple", "sample"]'),
    (7, '["must", "watch"]')
  ) AS t(id,jsondata);

现在我想要的是

addappend_to_json_array 这样的东西接受实际的 jsondata,它是一个 json-array 和我必须添加到该 jsondata 数组的 newString,这个函数应该返回更新了 json 数组。

UPDATE jsontesting
SET jsondata=append_to_json_array(jsondata, 'newString')
WHERE id = 7;

删除从 json 数据数组中的一个值,一个用于删除该值的函数。

我试图搜索 PostgreSQL 的文档,但没有找到任何东西。

【问题讨论】:

【参考方案1】:

要添加值,请使用 JSON 数组附加运算符 (||)

UPDATE jsontesting
SET jsondata = jsondata || '["newString"]'::jsonb
WHERE id = 7;

删除值如下所示

UPDATE jsontesting
SET jsondata = jsondata - "newString"
WHERE id = 7; 

连接到嵌套字段如下所示

UPDATE jsontesting
SET jsondata = jsonb_set(
  jsondata::jsonb,
  array['nestedfield'],
  (jsondata->'nestedfield')::jsonb || '["newString"]'::jsonb) 
WHERE id = 7;

【讨论】:

附加到已经非常大的数组的性能如何? postgres 是否需要加载整个行? 每次更新列时,PostgreSQL 都需要更新整行。 你能给我一个来源吗?我只是想多读一点。 @Rollo 任何 MVCC。他们都是这样工作的。它解决了隔离问题。当您更新一行时,该行在您提交之前对任何事务都不可见,但它必须对您自己的事务可见。所以你把桌子上的那一行写成死行。当你提交时,你让它活起来。在您提交之前,其他事务以之前的状态查看该行。 更好:SET jsondata = jsondata - 'newString'【参考方案2】:

要添加到 Evan Carroll 的答案,您可能需要执行以下操作以将列设置为空数组(如果它是 NULL)。如果列当前为 NULL,则附加运算符 (||) 不执行任何操作。

UPDATE jsontesting SET jsondata = (
    CASE
        WHEN jsondata IS NULL THEN '[]'::JSONB
        ELSE jsondata
    END
) || '["newString"]'::JSONB WHERE id = 7;

【讨论】:

我要么使用合并,要么将其写入条件。 @EvanCarroll 你可以添加一个例子吗? @RTW: postgresql 等有一个名为coalesce 的内置函数,其作用与此 case 表达式相同。 @RTW SET jsondata = COALESCE(jsondata, '[]'::JSONB) || '["newString"]'::JSONB 这应该是最佳答案....我想知道为什么它仍然为空,我怀疑这一点。赞一个,先生。【参考方案3】:

我在使用新的键值对附加到 postgres 中现有的 json 数据时遇到了类似的问题。 我可以使用附加运算符 || 解决此问题,如下所示:

UPDATE jsontesting
SET jsondata = jsondata::jsonb || '"add_new_data": true'
WHERE id = 7;

【讨论】:

以上是关于在 PostgreSQL 9.5+ 中追加(推送)和从 JSON 数组中删除的主要内容,如果未能解决你的问题,请参考以下文章

Linux CentOS 7 安装PostgreSQL 9.5 --步骤详解

CentOS 7 源码编译安装PostgreSQL 9.5

如何在 docker 上更改 postgreSQL 9.5 的时区?

CentOS 7 安装配置使用 PostgreSQL 9.5

PostgreSQL 9.5 - 行级安全/ROLE 最佳实践

markdown Zabbix 3使用PostgreSQL 9.5在CEntOS 7上安装