使用jsonb_set()进行条件更新

我在Postgres 11.3数据库中有一个带有jsonb列的表。

尝试更新嵌套数组名称中的所有对象"iProps"

如果路径{iProps -> value -> rules -> ao -> sc}是对象,则应将路径从对象更新为具有以下值的字符串: {iProps

-> value -> rules -> ao -> sc -> name}

如果{iProps -> value -> rules -> ao -> sc}不存在该路径,则该对象应保持不变。

使用查询测试设置:小提琴链接

所需结果:

{

"iProps": [

{

"value": {

"rules": [

{

"ao": {

"set": "get"

},

"name": "PRule"

},

{

"ao": {

"sc": "name1"

}

},

{

"ao": {

"sc": "name2"

}

},

{

"ao": {

"sc": "name3"

}

}

]

}

}

]

}

我已经修改了查询并链接到小提琴中。有人可以看看是否正确吗?

回答:

平原CASE应该有所作为。

UPDATE table_ t

SET value_ = jsonb_set(value_, '{iProps}', sub2.new_prop, false)

FROM (

SELECT id

, jsonb_agg(jsonb_set(prop, '{value, rules}', new_rules, false)

ORDER BY idx1) AS new_prop

FROM (

SELECT t.id, arr1.prop, arr1.idx1

, jsonb_agg( **CASE WHEN jsonb_typeof(rule # > '{ao,sc}') = 'object'

THEN jsonb_set(rule, '{ao,sc}', rule #> '{ao,sc,name}', false)

ELSE rule

END**

ORDER BY idx2) AS new_rules

FROM table_ t

, jsonb_array_elements(value_->'iProps') WITH ORDINALITY arr1(prop,idx1)

, jsonb_array_elements(prop->'value'->'rules') WITH ORDINALITY arr2(rule,idx2)

GROUP BY t.id, arr1.prop, arr1.idx1

) sub1

GROUP BY id

) sub2

WHERE t.id = sub2.id;

db

<>在这里

拨弄 (Postgres 11!)

为了同时满足您在更新中添加的第二个过滤器(必须是一个 对象

),请使用进行检查jsonb_typeof()

小提琴中的查询似乎不必要地复杂(tl;

dr)。同样,它不保留 。如果实际上不相关,请省略WITH ORDINALITYORDER BY进一步简化:

UPDATE table_ t

SET value_ = jsonb_set(value_, '{iProps}', sub2.new_prop, false)

FROM (

SELECT id

, jsonb_agg(jsonb_set(prop, '{value, rules}', new_rules, false)) AS new_prop

FROM (

SELECT t.id, prop

, jsonb_agg(CASE WHEN jsonb_typeof(rule #> '{ao,sc}') = 'object'

THEN jsonb_set(rule, '{ao,sc}', rule #> '{ao,sc,name}', false)

ELSE rule

END) AS new_rules

FROM table_ t

, jsonb_array_elements(value_->'iProps') prop

, jsonb_array_elements(prop->'value'->'rules') rule

GROUP BY t.id, prop

) sub1

GROUP BY id

) sub2

WHERE t.id = sub2.id;

db

<>在这里拨弄

通常,这仍会保留数组元素的顺序(与原始数组不同)。不能保证具有两个聚合级别。

以上是 使用jsonb_set()进行条件更新 的全部内容, 来源链接: utcz.com/qa/412517.html

回到顶部