当前位置: 首页 > 知识库问答 >
问题:

Postgresql:如何更新JSONB以在嵌套数组中添加新键

李兴庆
2023-03-14

如何更新JSONB以将新键添加到所有记录的嵌套数组(用于数组的所有项目)中。

我指的是表结构的链接:

CREATE TABLE orders (
    id   serial PRIMARY KEY,
    data jsonb
);

给定的json是:

{
  "Number": "555",
  "UserId": "1",
  "Items": [
    {
      "ProductId": "1", 
      "Name": "TV",
      "Price": "300.00"
    }, 
    {
      "ProductId": "2", 
      "Name": "Mechanical Keyboard",
      "Price": "120.00"
    }
  ]
}

要将新元素添加到每个数组项中,请执行以下查询:

UPDATE orders
SET data = jsonb_set(
    data, 
    '{Items}',      -- the array in which we operate
    to_jsonb(
    (WITH ar AS(
      WITH temp AS(
        SELECT data->'Items' AS items   -- the array in which we operate
        FROM orders
        WHERE id = 1    -- the filtered order we are updating
      )
      SELECT jsonb_set(
        jsonb_array_elements(items),
        '{Quantity}',   -- the new field we are adding
        '"1"',          -- the value of the new field
        true)
      FROM temp)
     SELECT (array_agg(ar.jsonb_set))
     FROM ar)),
  false)
WHERE id = 1;

执行上述查询后输出:

{
  "Number": "555",
  "UserId": "1",
  "Items": [
    {
      "ProductId": "1", 
      "Name": "TV",
      "Price": "300.00",
      "Quantity": "1"
    }, 
    {
      "ProductId": "2", 
      "Name": "Mechanical Keyboard",
      "Price": "120.00",
      "Quantity": "1"
    }
  ]
}

但是上面只会在id=1的地方更新json。对于orders中的所有行,需要进行哪些更改才能更新与上述相同的JSON?

共有2个答案

梅宏盛
2023-03-14

您不需要执行SELECT数据-

UPDATE orders
SET data = jsonb_set(
    data, 
    '{Items}',      -- the array in which we operate
    (SELECT jsonb_agg(jsonb_set(
        item,
        '{Quantity}',   -- the new field we are adding
        '"1"',          -- the value of the new field
        true))
     FROM jsonb_array_elements(data->'Items')) AS item, -- the array in which we operate
  false)
WHERE id = 1;

(我也摆脱了其他CTE,并将to_jsonb(array_agg(...))替换为jsonb_agg

现在,更新所有行所需做的就是省略WHERE子句。

伍胡媚
2023-03-14

一般提示,如果必须修改嵌套的JSON元素,这是一个严重的迹象,表明数据模型本可以设计得更好。但如果你别无选择,请使用辅助函数。它使事情变得更简单,代码更具可读性和可调试性。

create or replace function jsonb_insert_into_elements(jsonb, jsonb)
returns jsonb language sql immutable as $$
    select jsonb_agg(value || $2)
    from jsonb_array_elements($1)
$$;

现在,更新非常简单和优雅:

update orders
set data = jsonb_set(
    data, 
    '{Items}', 
    jsonb_insert_into_elements(data->'Items', '{"Quantity": "1"}'))
where id = 1 -- just skip this if you want to update all rows

数据库

 类似资料:
  • 假设我们有以下集合,我对此没有什么问题: > 我想增加“item_name”的价格:“my_item_two”,如果它不存在,应该将它追加到“items”数组中。

  • 具有以下数据模型: 我需要将所有价格键更新为新名称cost。在静态字段上很容易做到这一点,使用: 结果: 但是我也需要在分解数组中做这些。 在不知道细分数组中的项目数的情况下,我如何做到这一点?换句话说,我如何在jsonb数组的每个元素上应用函数。 非常感谢。

  • 这是我的架构:

  • 问题内容: 我有以下mongodb文件结构: 我已经能够使用$ elemMatch来更新操作中的字段,但是当我尝试对参数执行相同的操作(修改)时,它似乎不起作用。我想知道我应该尝试哪种其他方法,以便能够成功更新特定参数中的字段(通过其pid查找)。 我当前拥有但不起作用的更新代码如下所示: 问题答案: MongoDB 3.6及更高版本 MongoDB3.6及更高版本提供了一项新功能,该功能允许您使

  • 我正在尝试更新嵌套数组中的值,但无法使其工作。 我的对象是这样的 提前谢谢!

  • 我是JSON/JSONB数据类型的新手,在选择更深层次的JSONB元素时遇到了一些问题。 对此有什么建议吗?