合并PostgreSQL中的JSONB值?
使用||
运算符将产生以下结果:
select '{"a":{"b":2}}'::jsonb || '{"a":{"c":3}}'::jsonb ; ?column?
-----------------
{"a": {"c": 3}}
(1 row)
我希望能够实现以下结果(??
对于操作员来说只是一个占位符):
select '{"a":{"b":2}}'::jsonb ?? '{"a":{"c":3}}'::jsonb ; ?column?
-----------------
{"a": {"b": 2, "c": 3}}
(1 row)
因此,您可以看到顶级a
键的子值已“合并”,使得结果包含b
和c
。
如何在Postgres中“深度”合并两个 值?
如果可能的话,这可能吗?
一个更复杂的测试用例:
select '{"a":{"b":{"c":3},"z":true}}'::jsonb ?? '{"a":{"b":{"d":4},"z":false}}'::jsonb ; ?column?
-----------------
{"a": {"b": {"c": 3, "d": 4}, "z": false}}
(1 row)
原始“合并”并成为对象的另一个测试用例:
select '{"a":{"b":{"c":3},"z":true}}'::jsonb ?? '{"a":{"b":false,"z":false}}'::jsonb ; ?column?
-----------------
{"a": {"b": false, "z": false}}
(1 row)
回答:
您应该合并jsonb_each()
两个值都使用的未嵌套元素。在不平凡的查询中执行此操作可能会感到不舒服,因此我更喜欢这样的自定义函数:
create or replace function jsonb_my_merge(a jsonb, b jsonb)returns jsonb language sql as $$
select
jsonb_object_agg(
coalesce(ka, kb),
case
when va isnull then vb
when vb isnull then va
else va || vb
end
)
from jsonb_each(a) e1(ka, va)
full join jsonb_each(b) e2(kb, vb) on ka = kb
$$;
用:
select jsonb_my_merge( '{"a":{"b":2}, "d": {"e": 10}, "x": 1}'::jsonb,
'{"a":{"c":3}, "d": {"f": 11}, "y": 2}'::jsonb
)
jsonb_my_merge
------------------------------------------------------------------
{"a": {"b": 2, "c": 3}, "d": {"e": 10, "f": 11}, "x": 1, "y": 2}
(1 row)
您可以使用递归稍微修改函数,以使解决方案可以在任何嵌套级别上使用:
create or replace function jsonb_recursive_merge(a jsonb, b jsonb)returns jsonb language sql as $$
select
jsonb_object_agg(
coalesce(ka, kb),
case
when va isnull then vb
when vb isnull then va
when jsonb_typeof(va) <> 'object' then va || vb
else jsonb_recursive_merge(va, vb)
end
)
from jsonb_each(a) e1(ka, va)
full join jsonb_each(b) e2(kb, vb) on ka = kb
$$;
例子:
select jsonb_recursive_merge( '{"a":{"b":{"c":3},"x":5}}'::jsonb,
'{"a":{"b":{"d":4},"y":6}}'::jsonb);
jsonb_recursive_merge
------------------------------------------------
{"a": {"b": {"c": 3, "d": 4}, "x": 5, "y": 6}}
(1 row)
select jsonb_recursive_merge(
'{"a":{"b":{"c":{"d":{"e":1}}}}}'::jsonb,
'{"a":{"b":{"c":{"d":{"f":2}}}}}'::jsonb)
jsonb_recursive_merge
----------------------------------------------
{"a": {"b": {"c": {"d": {"e": 1, "f": 2}}}}}
(1 row)
最后,OP建议的功能变化形式(请参阅以下注释):
create or replace function jsonb_recursive_merge(a jsonb, b jsonb) returns jsonb language sql as $$
select
jsonb_object_agg(
coalesce(ka, kb),
case
when va isnull then vb
when vb isnull then va
when jsonb_typeof(va) <> 'object' or jsonb_typeof(vb) <> 'object' then vb
else jsonb_recursive_merge(va, vb) end
)
from jsonb_each(a) e1(ka, va)
full join jsonb_each(b) e2(kb, vb) on ka = kb
$$;
以上是 合并PostgreSQL中的JSONB值? 的全部内容, 来源链接: utcz.com/qa/421197.html