【问题标题】:Insert element in JSONB Array - Postgresql在 JSONB 数组中插入元素 - Postgresql
【发布时间】:2020-11-11 21:24:02
【问题描述】:

假设我有一张桌子:

SELECT * FROM settings;
| id | name    | strategies |
| -- | ---     | ---        |
| 1  | default | [{name: xyz, enabled: true}, {name: bot2, enabled: true}]  |
| 2  | new1    | [{name: bot2, enabled: true}, {name: xyz, enabled: false}] |

我想在bot2 之前添加一个新对象{name: bot1, enabled: true}

我正在尝试使用来自this answered question 的解决方案:

WITH bot2_index AS (SELECT
    pos- 1 AS bot2_index
FROM
    settings, 
    jsonb_array_elements(strategies) WITH ordinality arr(elem, pos)
WHERE
    NAME = 'default'
    AND elem->>'name' = 'bot2')    
UPDATE settings
SET strategies = jsonb_set(strategies, '{bot2_index}', '{
  "name": "bot1",
  "enabled": false
}', TRUE);

但我明白了

ERROR:  path element at position 1 is not an integer: "bot2_index"

bot2_indexbigint 类型,为什么这个语法不起作用?

我也尝试过其他变体,例如 bot2_indexbot2_index::intbot2_index::string,甚至将其作为两个单独的查询运行(如在接受的答案中),但它也不起作用。

编辑#1

这种语法有效,但它似乎替换了该索引处的元素,而不是在给定索引处的元素之前或之后附加元素 - 我怎样才能让它像 JS splice() 函数一样工作?

UPDATE settings
SET strategies = jsonb_set(strategies, concat('{',(SELECT
    pos- 1 AS bot2_index
FROM
    settings, 
    jsonb_array_elements(strategies) WITH ordinality arr(elem, pos)
WHERE
    NAME = 'default'
    AND elem->>'name' = 'js:bot2'),'}')::text[], '{
  "name": "bot1",
  "enabled": false
}', TRUE);

【问题讨论】:

    标签: postgresql sql-update jsonb postgresql-10


    【解决方案1】:

    首先,对于您当前的查询,您应该像下面这样使用它:

    WITH bot2_index AS (SELECT
        pos- 1 AS bot2_index
    FROM
        settings, 
        jsonb_array_elements(strategies) WITH ordinality arr(elem, pos)
    WHERE
        name = 'default'
        AND elem->>'name' = 'bot2')    
            
    UPDATE settings
    SET strategies = jsonb_set(strategies, array[bot2_index::text], '{
      "name": "bot1",
      "enabled": false
    }'::jsonb, false) from bot2_index;
    

    但查询将替换现有的 DEMO

    您应该使用jsonb_insert 而不是jsonb_set

    WITH bot2_index AS (SELECT
        pos- 1 AS bot2_index
    FROM
        settings, 
        jsonb_array_elements(strategies) WITH ordinality arr(elem, pos)
    WHERE
        name = 'default'
        AND elem->>'name' = 'bot2')    
            
    UPDATE settings
    SET strategies = jsonb_insert(strategies, array[bot2_index::text], '{
      "name": "bot1",
      "enabled": false
    }'::jsonb, false) from bot2_index;
      
    

    DEMO

    【讨论】:

    • 请立即查看
    猜你喜欢
    • 2020-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    相关资源
    最近更新 更多