跨多个记录更新 postgresql jsonb 对象数组中的属性值
Update the value of an attribute in a postgresql jsonb array of objects across muliple records
我正在尝试更新作为 jsonb 数组对象一部分的三个数据库记录中的值 tit,以使用 postgresql 和 python.
create table groups (name varchar, grp jsonb)
insert into groups (name, grp) values
('joe', [{"gid": "1", "ona": "joe", "tit": "group 1 "}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}]),
('harry', [{"gid": "1", "ona": "joe", "tit": "group 1 "}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
('moe' , [{"gid": "1", "ona": "joe", "tit": "group 1 "}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
我要得到结果:
('joe', [{"gid": "1", "ona": "joe", "tit": "newTitle Group 1'"}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}]),
('harry', [{"gid": "1", "ona": "joe", "tit": "newTitle Group 1'"}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
('moe' , [{"gid": "1", "ona": "joe", "tit": "newTitle Group 1'"}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
我还没有找到方法,请帮忙。似乎大多数 postgresql 9.5 功能都是针对 jsonb 对象而不是对象数组。
我尝试使用网络上的许多示例,但似乎都失败了。我也会考虑在实际查询中使用 where 子句语句来限制正在搜索的 jsonb 记录,例如包括 WHERE name IN ('harry', 'moe')
但现在只需要看看这个基本更新问题是如何解决的。
只需要在数据库中使用REPLACE()
函数,包括::text和::jsonb转换,不需要python 代码中的任何额外操作:
UPDATE groups
SET grp = REPLACE(grp::text, '"tit": "group 1 "','"tit": "newTitle Group 1 "')::jsonb
当然可以加where条件如WHERE name IN ('harry', 'moe')
限制更新
更新 1:
如果您需要对 jsonb 对象中的特定记录执行更新
比如
WHERE j->>'ona' = 'joe'
,然后在语句中使用 jsonb_array_elements()
函数作为 :
UPDATE groups AS g
SET grp = REPLACE(grp::text, '"tit": "group 1 "','"tit": "newTitle Group 1 "')::json
WHERE g.name IN ( SELECT g.name
FROM groups AS g
CROSS JOIN jsonb_array_elements(grp) AS j
WHERE j.value->>'ona' = 'joe' )
更新 2:
如果您想在 jsonb 列中动态找到所需的值(gid=1
在本例中)以导出路径,则可以使用jsonb_set()
功能为:
WITH T AS
(
SELECT ('{'||index-1||',tit}')::text[] AS path
FROM groups AS g2
CROSS JOIN jsonb_array_elements(grp)
WITH ORDINALITY arr(j,index)
WHERE j->>'gid'='1'
)
UPDATE groups AS g
SET grp = jsonb_set(grp,t.path,'"newTitle Group 1 "',false)
FROM t
我正在尝试更新作为 jsonb 数组对象一部分的三个数据库记录中的值 tit,以使用 postgresql 和 python.
create table groups (name varchar, grp jsonb)
insert into groups (name, grp) values
('joe', [{"gid": "1", "ona": "joe", "tit": "group 1 "}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}]),
('harry', [{"gid": "1", "ona": "joe", "tit": "group 1 "}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
('moe' , [{"gid": "1", "ona": "joe", "tit": "group 1 "}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
我要得到结果:
('joe', [{"gid": "1", "ona": "joe", "tit": "newTitle Group 1'"}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}]),
('harry', [{"gid": "1", "ona": "joe", "tit": "newTitle Group 1'"}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
('moe' , [{"gid": "1", "ona": "joe", "tit": "newTitle Group 1'"}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
我还没有找到方法,请帮忙。似乎大多数 postgresql 9.5 功能都是针对 jsonb 对象而不是对象数组。
我尝试使用网络上的许多示例,但似乎都失败了。我也会考虑在实际查询中使用 where 子句语句来限制正在搜索的 jsonb 记录,例如包括 WHERE name IN ('harry', 'moe')
但现在只需要看看这个基本更新问题是如何解决的。
只需要在数据库中使用REPLACE()
函数,包括::text和::jsonb转换,不需要python 代码中的任何额外操作:
UPDATE groups
SET grp = REPLACE(grp::text, '"tit": "group 1 "','"tit": "newTitle Group 1 "')::jsonb
当然可以加where条件如WHERE name IN ('harry', 'moe')
限制更新
更新 1:
如果您需要对 jsonb 对象中的特定记录执行更新 比如
WHERE j->>'ona' = 'joe'
,然后在语句中使用 jsonb_array_elements()
函数作为 :
UPDATE groups AS g
SET grp = REPLACE(grp::text, '"tit": "group 1 "','"tit": "newTitle Group 1 "')::json
WHERE g.name IN ( SELECT g.name
FROM groups AS g
CROSS JOIN jsonb_array_elements(grp) AS j
WHERE j.value->>'ona' = 'joe' )
更新 2:
如果您想在 jsonb 列中动态找到所需的值(gid=1
在本例中)以导出路径,则可以使用jsonb_set()
功能为:
WITH T AS
(
SELECT ('{'||index-1||',tit}')::text[] AS path
FROM groups AS g2
CROSS JOIN jsonb_array_elements(grp)
WITH ORDINALITY arr(j,index)
WHERE j->>'gid'='1'
)
UPDATE groups AS g
SET grp = jsonb_set(grp,t.path,'"newTitle Group 1 "',false)
FROM t