Postgresql 更新 JSON 列保留一些键值并将附加键值添加为空

Posted

技术标签:

【中文标题】Postgresql 更新 JSON 列保留一些键值并将附加键值添加为空【英文标题】:Postgresql Update JSON Column Retaining Some KeyValues and Adding Additional KeyValue as null 【发布时间】:2016-09-06 15:51:03 【问题描述】:

我正在尝试将metadata JSONB 列用于多租户应用程序。每个租户的每个user 必须具有相同的metadata,但租户具有不同的metadata 字段。

为了使每个租户的所有用户元数据保持同步,当租户管理员修改元数据字段时,我需要确保所有用户的元数据 JSONB 列都按照以下条件更新:

    如果元数据字段/键已经存在,则需要保留该值 如果元数据字段/键是新的,则键需要添加空值 如果有任何元数据字段/键未包含在更新列表中,则应从 JSON 对象中删除它们

例如,租户 #1 的所有用户都分配了以下元数据: "EmployeeNo" : 123, "HireDate" : "2012-10-10", "Age" : 43 并且管理员决定他们不关心年龄,但他们确实想开始跟踪 ParkingSpace。

我需要新的元数据记录来保留 EmployeeNo 和 HireDate 值,删除 Age 键/值,并添加具有空值的 ParkingSpace 键。 "EmployeeNo" : 123, "HireDate" : "2012-10-10", "ParkingSpace" : null .

我原以为我可以运行类似于以下内容的更新查询,它返回一个 JSONB 对象,如果键存在则选择值,如果键不存在则选择 null:

UPDATE users SET metadata = metadata[keys: 'EmployeeNo', 'HireDate', 'ParkingSpace'] WHERE tenant_id = 1;

显然这不起作用,但希望它表明问题所在?

【问题讨论】:

【参考方案1】:

更新:我可能误解了你的问题。也许你想要这样的东西:

UPDATE users
SET metadata = (SELECT json_object_agg(n,metadata->>n) FROM unnest(ARRAY['EmployeeNo','HireDate','ParkingSpace']) AS t(n))

此解决方案涉及通过仅从原始 metadata 中提取您想要的字段来创建一个全新的 jsonb 对象。要复制的字段被指定为您可以轻松自定义的数组。

原答案:我认为应该这样做:

UPDATE users
SET metadata = (metadata - 'Age') || '"ParkingSpace": null'::jsonb;

我正在使用 || 运算符将 2 个 jsonb 对象合并为一个,而 - 运算符用于删除键/值对。

【讨论】:

我可能会完成这项工作,理想情况下我不想跟踪被删除的列(在本例中为“年龄”)。 我重读了你的问题并更新了我的答案。让我知道这是否有效。 甜蜜,您更新的答案似乎完美无缺!现在我将不得不查看有关 why 的文档(尤其是 json_object_agg 和 unnest 数组)。谢谢!

以上是关于Postgresql 更新 JSON 列保留一些键值并将附加键值添加为空的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL:具有选择性列的 row_to_json [重复]

使用 jooq/postgresql 从 json 中提取键/值对 - java

在 postgresql JSON 中添加列

PostgreSql INSERT 插入数据判断数据是否存在,存在则更新,不存在则插入

PostgreSql INSERT 插入数据判断数据是否存在,存在则更新,不存在则插入

在 PostgreSQL 函数中基于 JSON 更新表