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

Postgresql Update JSON Column Retaining Some KeyValues and Adding Additional KeyValue as null

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

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

  1. 如果元数据field/key已经存在,需要保留该值
  2. 如果元数据field/key是新的,key需要添加一个空值
  3. 如果有任何元数据 fields/keys 未包含在更新列表中,应将其从 JSON 对象中删除

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

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

我原以为我可以 运行 一个类似于下面的更新查询,它 returns 一个 JSONB 对象,如果键存在,它会选择值,并且如果没有则为 null:

UPDATE users SET metadata = metadata[keys: 'EmployeeNo', 'HireDate', 'ParkingSpace'] WHERE tenant_id = 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 对象合并为一个的 || 运算符和删除 key/value 对的 - 运算符。