【问题标题】:Updating jsonb field using concatenation operator in postgres在 postgres 中使用连接运算符更新 jsonb 字段
【发布时间】:2019-09-13 16:54:49
【问题描述】:

我正在尝试使用 postgres 中的连接运算符更新其中包含嵌套 json 对象的 jsonb 字段,如 dbfidde

但是,如果我运行以下脚本,它会删除所有其他字段

UPDATE t 
SET details = details || '{"name": {"firstname": "newname"},"address":{"city":"newCity"}}'
WHERE details -> 'name' ->>'firstname'='myname'

它从更新的字段中删除"lastname" 字段

我也尝试使用jsonb_set 进行更新,但我不确定如何使用jsonb_set 更新多个属性

【问题讨论】:

  • 您能解释一下您要达到的目标吗?据我了解:旧 JSON {"a":"b"} 扩展为 {"a":"c"}。但是比你有两次相同的密钥...
  • 您的 dbfiddle 似乎准确地显示了您的要求。您是说当您在真实数据库上执行此操作时,行为会有所不同?
  • @JSpratt 问题中的查询删除了dbfiddle.uk/…中的“lastname”属性
  • @S-Man 我正在尝试在同一查询中更新 name 对象中的 firstname 属性和 address 对象中的 city 属性

标签: postgresql jsonb


【解决方案1】:

|| 方式不起作用,因为新名称值为{"firstname":"newname"}。这将替换完整的旧值 {"firstname": "myname","lastname":"last"},从而删除 lastname 属性。这种方法只有在您处理顶级字段时才有效。但是您想更新嵌套对象。

在这种情况下,我认为无法绕过两个单独的 jsonb_set() 调用。一种可能的方法是嵌套它们:

demo:db<>fiddle

UPDATE t
SET details = 
        jsonb_set(
            jsonb_set(details, '{name,firstname}','"newname"'), 
            '{address,city}', 
            '"newCity"'
        )
WHERE details -> 'name' ->> 'firstname' = 'myname';
  1. 更新原来的details字段;通过给定路径 '{name,firstname}' 设置新的 firstname
  2. 生成的 JSON 对象可直接用于后续更新 city 值,方法相同。

【讨论】:

  • 我仍在想办法,如果我必须使用上述查询更新 5 个甚至更多的嵌套对象。你有什么想法吗?
  • 也许你可以用你的真实数据发布一个小提琴?我可以看看
  • 如果我必须在单个查询中更新 firstname, last name, homeaddress and workaddress 怎么办。这是小提琴dbfiddle.uk/…
  • 地址是 json 对象。您要替换整个值还是只替换 city 元素?
  • dbfiddle.uk/… 在这种特殊情况下可以聚合名称对象,因为没有其他子元素。所以可以一次性替换整个名称对象。由于两个城市有不同的路径,您将需要两个不同的调用。
猜你喜欢
  • 1970-01-01
  • 2015-10-06
  • 1970-01-01
  • 2023-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-16
  • 2017-02-05
相关资源
最近更新 更多