Postgresql:从 json 值的嵌套数组字段编辑特定字段
Postrgesql : Edit a specific field from a nested array field of a jsonb value
table:
table Bar(
id int,
my_json jsonb
)
my_json
的示例:
{
"foo": "bar",
"columns": [
{
"type": "integer",
"field": "myField",
"children": [
{
"type": "integer",
"field": "myField"
}
]
},
{
"type": "integer",
"field": "otherField",
"children": [
{
"type": "integer",
"field": "myField"
}
]
},
{
"type": "integer",
"field": "baz",
"children": null
}
]
}
我需要将所有 "type": "integer"
更改为 "type": "string"
,其中匹配的 "field"
等于 "myField"
。
我用下一个 sql 查询制作了 lvl 1(在 columns
lvl):
with query as (
select ('{columns,' || index - 1 || ',type}')::text[] as path,
b.id
from Bar b,
jsonb_array_elements(my_json -> 'columns') with ordinality arr(col, index)
where col ->> 'field' = 'myField'
and col ->> 'type' = 'integer'
)
update Bar b
set my_json = jsonb_set(b.my_json, query.path, '"string"', false)
from query
where b.id = query.id;
我必须使用可能为 null 的嵌套数组 children
达到 2 级(理想情况下理解任何级别),但我不知道该怎么做。
我做到了!这是我找到的解决方案:
with non_null_children as (
select index - 1 as idx,
col,
b.id as bar_id
from Bar b,
jsonb_array_elements(my_json -> 'columns') with ordinality arr(col, index)
where col ->> 'children' is not null
), query as (
select ('{columns,' || nnc.idx || ',children,' || index - 1 || ',type}')::text[] as path,
b.id
from Bar b,
non_null_children nnc,
jsonb_array_elements(nnc.col -> 'children') with ordinality arr(col2, index)
where b.id = nnc.bar_id
and col2 ->> 'field' = 'myField'
and col2 ->> 'type' = 'integer'
)
update Bar b
set my_json = jsonb_set(b.my_json, query.path, '"string"', false)
from query
where b.id = query.id;
解释:
- 我列出了所有包含子项的项目,每个项目都与其
columns
索引及其 Bar id -> non_null_children
- 对于每个Bar id / column index,我可以进行匹配字段操作,就像lvl 1一样。
不知道这是不是最优化的方案,如果觉得有必要,欢迎改进。
table:
table Bar(
id int,
my_json jsonb
)
my_json
的示例:
{
"foo": "bar",
"columns": [
{
"type": "integer",
"field": "myField",
"children": [
{
"type": "integer",
"field": "myField"
}
]
},
{
"type": "integer",
"field": "otherField",
"children": [
{
"type": "integer",
"field": "myField"
}
]
},
{
"type": "integer",
"field": "baz",
"children": null
}
]
}
我需要将所有 "type": "integer"
更改为 "type": "string"
,其中匹配的 "field"
等于 "myField"
。
我用下一个 sql 查询制作了 lvl 1(在 columns
lvl):
with query as (
select ('{columns,' || index - 1 || ',type}')::text[] as path,
b.id
from Bar b,
jsonb_array_elements(my_json -> 'columns') with ordinality arr(col, index)
where col ->> 'field' = 'myField'
and col ->> 'type' = 'integer'
)
update Bar b
set my_json = jsonb_set(b.my_json, query.path, '"string"', false)
from query
where b.id = query.id;
我必须使用可能为 null 的嵌套数组 children
达到 2 级(理想情况下理解任何级别),但我不知道该怎么做。
我做到了!这是我找到的解决方案:
with non_null_children as (
select index - 1 as idx,
col,
b.id as bar_id
from Bar b,
jsonb_array_elements(my_json -> 'columns') with ordinality arr(col, index)
where col ->> 'children' is not null
), query as (
select ('{columns,' || nnc.idx || ',children,' || index - 1 || ',type}')::text[] as path,
b.id
from Bar b,
non_null_children nnc,
jsonb_array_elements(nnc.col -> 'children') with ordinality arr(col2, index)
where b.id = nnc.bar_id
and col2 ->> 'field' = 'myField'
and col2 ->> 'type' = 'integer'
)
update Bar b
set my_json = jsonb_set(b.my_json, query.path, '"string"', false)
from query
where b.id = query.id;
解释:
- 我列出了所有包含子项的项目,每个项目都与其
columns
索引及其 Bar id ->non_null_children
- 对于每个Bar id / column index,我可以进行匹配字段操作,就像lvl 1一样。
不知道这是不是最优化的方案,如果觉得有必要,欢迎改进。