【问题标题】:How to update PostgreSQL array of jsonb如何更新 jsonb 的 PostgreSQL 数组
【发布时间】:2019-08-30 19:06:15
【问题描述】:

我有一张这样的桌子:

id: integer,
... other stuff...,
comments: array of jsonb

其中 cmets 列具有以下结构:

[{
        "uid": "comment_1",
        "message": "level 1 - comment 1",
        "comments": [{
            "uid": "subcomment_1",
            "message": "level 2 - comment 1",
            "comments": []
        }, {
            "uid": "subcomment_2",
            "message": "level 1 - comment 2",
            "comments": []
        }]
    },
    {
        "uid": "P7D1hbRq4",
        "message": "level 1 - comment 2",
        "comments": []
    }
]

我需要更新一个特定的字段,例如:comments[1](with uid = comment_1) -> comments[2] (with uid = subcomment_2) -> message = 'comment edited'

我是 postgresql 的新手,我无法弄清楚如何做到这一点,甚至没有接近。我设法合并对象并更改级别 1 的消息:

UPDATE tasks
    set comments[1] = comments[1]::jsonb || $$
      {
        "message": "something",
      }$$::jsonb
where id = 20;

但这是我能做到的。

对正确方向的任何提示?

乐: 我已经走到这一步了:

UPDATE tasks
set comments[1] = jsonb_set(comments[1], '{comments,1, message}', '"test_new"')
where id = 20;

当然,我可以从 javascript 获得这条路径,但这是最佳实践吗?使用 javascript 数组中的索引感觉不舒服。 我应该尝试编写一个 sql 函数来获取数组并使用“uid”作为键吗?还有其他更简单的使用“uid”搜索/选择的方法吗?

LLE

我无法通过this question 的建议让它工作(我阅读并尝试过) 下面的代码什么也不返回:

-- get index for level 2
select pos as elem_index
from tasks,
     jsonb_array_elements(comments[0]->'comments') with ordinality arr(elem, pos)
where tasks.id = 20 and
      elem ->>'uid'='subcomment_1';

而且我需要它的几个级别,所以它不是完全重复的。

【问题讨论】:

标签: postgresql jsonb postgresql-11


【解决方案1】:

首先,您不能更新列的一部分(数组的元素),而只能更新整个列。

接下来,您应该了解路径(jsonb_set() 函数的第二个参数)的含义。

最后,函数的第三个参数是一个有效的 json,所以一个简单的文本值必须用单引号和双引号括起来。

update tasks
set comments = jsonb_set(comments, '{0, comments, 1, message}', '"comment edited"')
where id = 1;

路径:

  • 0 - 外部数组的第一个元素(元素从 0)
  • cmets - 带有键 comments 的对象
  • 1 - 的第二个元素 comments 数组
  • message - 上面的对象message 元素。

Db<>fiddle.

【讨论】:

  • 我相信我开始理解路径的概念了。我已经尝试过您的代码,但在我修改它之前它不起作用:set comments[1] = jsonb_set(comments[1], '{comments, 1, message}', '"comment edited"') 因为我的列是 jsonb 数组(也许?)所以如果我这样使用,它就可以工作。
  • 好吧,我没有注意到这是难以理解的jsonb[]。请阅读jsonb vs jsonb array for multiple addresses for a customerpostgres change jsonb array to jsonb。不幸的是,the linked answer 是这个问题的唯一答案。结构过于复杂,无法找到更简单的解决方案,而且我知道它不是开箱即用的补救措施,需要进一步工作。 Postgres 不是 Python...
  • 我读过。所以你的建议是从 jsonb[] 切换到 jsonb?具有讽刺意味的是,我认为拥有 json 数组会更容易,因为后续数据结构也具有递归属性“cmets”作为 json 数组。
  • 在数据库世界中,简单是一种真正的美德。数据结构应该反映在相关的表和原始列中。当然,json 在这里也可以让生活更轻松,但它不是它的自然栖息地。
  • 所以,如果你需要更新一个深度嵌套的 json 对象,这表明你应该将 json 结构翻译成数据库语言(表和列)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-16
相关资源
最近更新 更多