使用特定键更新 Postgres 中的 JSON 数组

Update JSON Array in Postgres with specific key

我有一个复杂的数组,在 table 列中如下所示:

{
"sometag": {},
"where": [
    {
        "id": "Krishna",
        "nick": "KK",
        "values": [
            "0"
        ],
        "function": "ADD",
        "numValue": [
            "0"
        ]
    },
    {
        "id": "Krishna1",
        "nick": "KK1",
        "values": [
            "0"
        ],
        "function": "SUB",
        "numValue": [
            "0"
        ]
    }
],
"anotherTag": [],
"TagTag": {
    "tt": "tttttt",
    "tt1": "tttttt"
}

在这个数组中,我想更新 id: "Krishna" 的函数和 numValue。

请帮忙。

这真的很讨厌,因为

  1. 更新 JSON 数组中的元素总是需要扩展数组
  2. 在上:数组是嵌套的
  3. 要更新的元素的标识符是兄弟而非父元素,这意味着,您必须按兄弟过滤

所以我想到了一个解决方案,但我想声明:您应该避免将此作为常规数据库操作!更好的是:

  1. 在后端解析你的JSON并在你的后端代码中进行操作
  2. 规范化数据库中的 JSON 如果这是一项常见任务,意思是:创建具有适当列的 table 并将 JSON 提取到 table结构体。不要将整个 JSON 个对象存储在数据库中!这将使每一项任务变得更加容易,并且性能更高!

demo:db<>fiddle

SELECT
    jsonb_set(                                                                                -- 5
        (SELECT mydata::jsonb FROM mytable), 
        '{where}', 
        updated_array
    )::json
FROM (
    SELECT
        jsonb_agg(                                                                            -- 4
            CASE WHEN array_elem ->> 'id' = 'Krishna' THEN
                jsonb_set(                                                                    -- 3
                    jsonb_set(array_elem.value::jsonb, '{function}', '"ADDITION"'::jsonb),    -- 2
                    '{numValue}', 
                    '["0","1"]'::jsonb
                )
            ELSE array_elem::jsonb END
        ) as updated_array
    FROM mytable,
        json_array_elements(mydata -> 'where') array_elem                                     -- 1
) s
  1. 将嵌套数组元素提取为每行一个元素
  2. 替换function值。请注意从类型 json 到类型 jsonb 的转换。这是必要的,因为没有 json_set() 函数,只有 jsonb_set()。当然,如果您只有类型 jsonb,则不需要强制转换。
  3. 替换numValue
  4. 重新聚合数组
  5. 用新创建的数组对象替换原来JSON对象的where值。