我在Postgres 11.3数据库中有一个带有jsonb列的表。
jsonb
尝试更新嵌套数组名称中的所有对象"iProps"。
"iProps"
如果路径{iProps -> value -> rules -> ao -> sc}是对象,则应将路径从对象更新为具有以下值的字符串: {iProps -> value -> rules -> ao -> sc -> name}
{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应该有所作为。
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()。
jsonb_typeof()
小提琴中的查询似乎不必要地复杂(tl; dr)。同样,它不保留 数组元素的原始顺序 。如果实际上不相关,请省略WITH ORDINALITY并ORDER BY进一步简化:
WITH ORDINALITY
ORDER 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 <>在这里拨弄
通常,这仍会保留数组元素的顺序(与原始数组不同)。不能保证具有两个聚合级别。