postgresql:更新一个 jsonb 对象中的多个值
postgresql: update multiple values within one jsonb object
我最近遇到了一个关于我的 Postgresql 数据库中 JSONB 数据类型的问题。
我的专栏有一个相当复杂的结构(假设 table 称为 RATING,列名称 FOOD_VALUE - 组成它),例如,如下所示:
{
"food": {
"type": {
"id": 1,
"name": "good"
},
"category": {
"id": 2,
"name": "Vegetables"
},
"others": {
"descr": "It's all good"
}
}
}
这是一个示例,实际可能有数百个值(当然是嵌套的)。
我想更新几个值(在这个例子中是两个 -> food.type.name + food.category.id)而不修改结构本身。
这是期望的输出:
{
"food": {
"type": {
"id": 1,
"name": "not bad"
},
"category": {
"id": 1,
"name": "Vegetables"
},
"others": {
"descr": "It's all good"
}
}
}
使用 JSONB_SET 我只能在同一列中操作一条记录 -> RATING.FOOD_VALUE ...我知道我也可以嵌套它们,但考虑到我需要更新 40 多个值,这可能会让人难以阅读(因此难以维护)
所以这个:
UPDATE rating
SET food_value = jsonb_set(
jsonb_set(food_value,'{food, type, name}', '"not bad"')::jsonb
,'{food, category, id}','"1"'::jsonb)
WHERE ....
绝对不行..
实现此目的的另一种方法是使用 JSON_BUILD_OBJECT:
UPDATE rating
SET food_value = food_value
|| jsonb_build_object('food', jsonb_build_object('type', jsonb_build_object('name', 'not bad')))
|| jsonb_build_object('food', jsonb_build_object('category', jsonb_build_object('id', 1)))
... and so on
WHERE ....
这在维护、可读性等方面看起来更有前途。但我在这里遇到的问题是它改变了 JSON 文件格式的结构:(所以上面的查询将结果
{
"food": {
"type": {
"name": "not bad"
},
"category": {
"id": 1
}
}
}
知道如何摆脱这种困境吗?我需要找到一种方法来更新复杂 JSON 结构中的数十个字段而不修改结构本身(只是值)
create type t_json_val as (path text[], val jsonb);
create or replace function jsonb_mset(a jsonb, variadic b t_json_val[])
returns jsonb
immutable
language plpgsql
as $$
-- Set multiple jsonb values at once
declare
bb t_json_val;
begin
foreach bb in array b loop
a := jsonb_set(a, bb.path, bb.val);
end loop;
return a;
end $$;
select jsonb_pretty(jsonb_mset('{
"food": {
"type": {
"id": 1,
"name": "good"
},
"category": {
"id": 2,
"name": "Vegetables"
},
"others": {
"descr": "It''s all good"
}
}
}',
('{food, type, name}', '"not bad"'),
('{food, category, id}', '"1"')));
┌──────────────────────────────────────┐
│ jsonb_pretty │
├──────────────────────────────────────┤
│ { ↵│
│ "food": { ↵│
│ "type": { ↵│
│ "id": 1, ↵│
│ "name": "not bad" ↵│
│ }, ↵│
│ "others": { ↵│
│ "descr": "It's all good"↵│
│ }, ↵│
│ "category": { ↵│
│ "id": "1", ↵│
│ "name": "Vegetables" ↵│
│ } ↵│
│ } ↵│
│ } │
└──────────────────────────────────────┘
我最近遇到了一个关于我的 Postgresql 数据库中 JSONB 数据类型的问题。
我的专栏有一个相当复杂的结构(假设 table 称为 RATING,列名称 FOOD_VALUE - 组成它),例如,如下所示:
{
"food": {
"type": {
"id": 1,
"name": "good"
},
"category": {
"id": 2,
"name": "Vegetables"
},
"others": {
"descr": "It's all good"
}
}
}
这是一个示例,实际可能有数百个值(当然是嵌套的)。
我想更新几个值(在这个例子中是两个 -> food.type.name + food.category.id)而不修改结构本身。
这是期望的输出:
{
"food": {
"type": {
"id": 1,
"name": "not bad"
},
"category": {
"id": 1,
"name": "Vegetables"
},
"others": {
"descr": "It's all good"
}
}
}
使用 JSONB_SET 我只能在同一列中操作一条记录 -> RATING.FOOD_VALUE ...我知道我也可以嵌套它们,但考虑到我需要更新 40 多个值,这可能会让人难以阅读(因此难以维护)
所以这个:
UPDATE rating
SET food_value = jsonb_set(
jsonb_set(food_value,'{food, type, name}', '"not bad"')::jsonb
,'{food, category, id}','"1"'::jsonb)
WHERE ....
绝对不行..
实现此目的的另一种方法是使用 JSON_BUILD_OBJECT:
UPDATE rating
SET food_value = food_value
|| jsonb_build_object('food', jsonb_build_object('type', jsonb_build_object('name', 'not bad')))
|| jsonb_build_object('food', jsonb_build_object('category', jsonb_build_object('id', 1)))
... and so on
WHERE ....
这在维护、可读性等方面看起来更有前途。但我在这里遇到的问题是它改变了 JSON 文件格式的结构:(所以上面的查询将结果
{
"food": {
"type": {
"name": "not bad"
},
"category": {
"id": 1
}
}
}
知道如何摆脱这种困境吗?我需要找到一种方法来更新复杂 JSON 结构中的数十个字段而不修改结构本身(只是值)
create type t_json_val as (path text[], val jsonb);
create or replace function jsonb_mset(a jsonb, variadic b t_json_val[])
returns jsonb
immutable
language plpgsql
as $$
-- Set multiple jsonb values at once
declare
bb t_json_val;
begin
foreach bb in array b loop
a := jsonb_set(a, bb.path, bb.val);
end loop;
return a;
end $$;
select jsonb_pretty(jsonb_mset('{
"food": {
"type": {
"id": 1,
"name": "good"
},
"category": {
"id": 2,
"name": "Vegetables"
},
"others": {
"descr": "It''s all good"
}
}
}',
('{food, type, name}', '"not bad"'),
('{food, category, id}', '"1"')));
┌──────────────────────────────────────┐
│ jsonb_pretty │
├──────────────────────────────────────┤
│ { ↵│
│ "food": { ↵│
│ "type": { ↵│
│ "id": 1, ↵│
│ "name": "not bad" ↵│
│ }, ↵│
│ "others": { ↵│
│ "descr": "It's all good"↵│
│ }, ↵│
│ "category": { ↵│
│ "id": "1", ↵│
│ "name": "Vegetables" ↵│
│ } ↵│
│ } ↵│
│ } │
└──────────────────────────────────────┘