合并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键的子值已“合并”,使得结果包含bc

如何在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

回到顶部