如何根据属性名称更新JSONB数组?

时间:2019-05-06 16:44:57

标签: json postgresql

我想基于objectId更新以下JSON数组的字段(存储在JSONB数据类型的列中)。

        [
            {
                objectId: 'gDKn1jM5d',
                objectType: 'type1',
                posX: 50,
                posY: 100,
            },
            {
                objectId: '4dg5E8BDv',
                objectType: 'type2',
                posX: 50,
                posY: 100,
            },
            {
                objectId: 'ZmCwOf5N2',
                objectType: 'type3',
                posX: 100,
                posY: 150,
            }
        ]

在Mongodb中,我可以使用一个简单的更新语句,但无法在postgres中找到方法。

例如,我想将所有具有objectId'ZmCwOf5N2'的数组元素更新为posX值300(这意味着它只会影响第三个数组项)。

我正在寻找一个普通的SQL语句来执行更新。 postgres版本是11。

由于我将数据库用作服务提供者,因此我无法安装扩展。但是,如果没有简单的方法来完成更新语句,我将能够使用例如添加postgres函数。 C代码。

1 个答案:

答案 0 :(得分:1)

UPDATE tbl t
SET    js = 
   (
   SELECT jsonb_agg(CASE WHEN elem->>'objectId' = 'ZmCwOf5N2'
                         THEN jsonb_set(elem, '{posX}', to_jsonb(int '300'))
                         ELSE elem
                    END) AS  js1 
   FROM   jsonb_array_elements(t.js) elem
   )
WHERE  t.js @> '[{"objectId": "ZmCwOf5N2"}]';

请注意,此..

  • 如果缺少'posX'密钥,则添加
  • 即使没有任何变化也更新行

仅更新现有键,并且仅当更新实际更改了值时才更新行:

UPDATE tbl t
SET    js = 
   (
   SELECT jsonb_agg(CASE WHEN elem->>'objectId' = 'ZmCwOf5N2'
                         THEN jsonb_set(elem, '{posX}', to_jsonb(int '300'), false)  -- !
                         ELSE elem
                    END) AS  js1 
   FROM   jsonb_array_elements(t.js) elem
   )
WHERE  t.js @> '[{"objectId": "ZmCwOf5N2"}]'
AND    js <>
   (
   SELECT jsonb_agg(CASE WHEN elem->>'objectId' = 'ZmCwOf5N2'
                         THEN jsonb_set(elem, '{posX}', to_jsonb(int '300'), false)
                         ELSE elem
                    END) AS  js1 
   FROM   jsonb_array_elements(t.js) elem
   );  --!

请参阅: