如何从Postgres JSONB数组中深度删除对象?

如何从Postgres JSONB数组中深度删除对象?,json,postgresql,jsonb,Json,Postgresql,Jsonb,我使用的是Postgres 10.12,我有一个reels_数据表,它有一个jsonb列,名为blocks,它是一个对象数组,每个对象都有自己的类型和数据对象。例如: [ { 类型:LOGO, 数据:{ 影像识别码:399 } }, { 类型:联系人信息, 数据:{ 电邮:, 电话:, 网址:, 姓名:鲍勃, 职位名称:开发人员 } }, { 类型:媒体, 数据:{ 播放列表:[ { id:134e3b49-fe08-43b9-b13a-dc886ec0af61, 名称:无标题播放列表, 媒体:

我使用的是Postgres 10.12,我有一个reels_数据表,它有一个jsonb列,名为blocks,它是一个对象数组,每个对象都有自己的类型和数据对象。例如:

[ { 类型:LOGO, 数据:{ 影像识别码:399 } }, { 类型:联系人信息, 数据:{ 电邮:, 电话:, 网址:, 姓名:鲍勃, 职位名称:开发人员 } }, { 类型:媒体, 数据:{ 播放列表:[ { id:134e3b49-fe08-43b9-b13a-dc886ec0af61, 名称:无标题播放列表, 媒体:[ { id:265, 文件ID:8a7519b8-92dc-4978-a239-5b25d66caf45, 项目类型:轨道, 名称:Test, 时长:104.749 }, { 身份证号码:266, 文件UUID:7409bbd5-f8a0-46f2-a077-78c14a4dcd80, 项目类型:轨道, 名称:试验2, 持续时间:144.163 }, { 身份证号码:267, 文件UUID:14c0d325-bfce-4ac5-a4f6-3edaa0e86ac5, 项目类型:轨道, 名称:试验3, 持续时间:143.871 } ] } ] } } ] 我的挑战是,如果用户删除ID为265的媒体,则必须从类型为media的所有块中提取该媒体,并使其更复杂,从播放列表阵列中的所有播放列表中提取该媒体

这些块可以是任意顺序的,所以我不能假设索引为2。可能有一个或10个播放列表,要删除的媒体可能不存在或存在于其中的几个播放列表中


我是否可以编写一个Postgres查询来删除ID为x的所有媒体?还是将其编写为SQL查询以检索上述数据、使用JavaScript添加一些数据处理,然后构建并提交SQL事务以使用新数据更新几行更好?效率是最重要的,不会对数据库服务器征税。

考虑到您的结构是固定的,请尝试以下查询:

with cte as(
select 
id,
data->'type' "type",
data->'data' "data",
playlists->>'id', 
playlists->>'name',
jsonb_build_object('id', playlists->>'id','name', playlists->>'name', 'media',json_agg(z.media) ) "playlists"
from reels_data  t1
left join lateral jsonb_array_elements(t1.blocks) x(data) on true
 left join lateral jsonb_array_elements(x.data->'data'->'playlists') y(playlists) on true
left join lateral jsonb_array_elements(y.playlists->'media') z(media) on true
where  z.media->>'id' is null or z.media->>'id' <>'265' 
group by 1,2,3,4,5
), 
cte1 as
(
select id,jsonb_agg(final) "final_data" from (
select 
id,
type, 
data,
playlists,
jsonb_build_object('type',type,'data',case when type='"MEDIA"' then jsonb_build_object('playlists',jsonb_agg(playlists)) else data end) "final"
from 
cte
group by 1,2,3,4) t1
group by 1
)

update reels_data t1 set blocks= t2."final_data" from cte1 t2 where t1.id=t2.id

它将替换具有给定id的所有对象


你是什么版本的Postgresqlusing@AkhileshMishra版本10.12。我更新了我的帖子来反映这一点。谢谢!这真的很接近,它几乎可以工作,除了当我在playlists数组中有两个playlist对象时,其中一个被完全删除。另一个相关的评论:这种方法的一个缺点是,如果playlist JSON模式突然有了新的属性,那么每次都必须更新这个SQL查询,以便它构建正确的jsonb字段。糟糕的是,Postgres没有一种方法可以使用所有现有属性构建一个对象。如果您想要完整的动态解决方案,那么可以通过递归函数及其调用来实现,但对于这一点,应该有一个包含所有可能场景的示例json。