[英]How to remove/update a JSONB array element where key equals a value?
我想从属性等于设定值的 JSONB 数组中删除/替换一个元素。 我已经找到了许多可以完成此操作的功能,但我想知道是否有一种方法可以做到这一点,因为我有数据库限制?
这是一个示例 JSONB 值:
[
{ "ID": "valuea" },
{ "ID": "valueb" },
{ "ID": "valuec" }
]
我想用一条更新语句删除第二个数组 position,其中 ID 等于valueb
。 我想这可以找到数组中的位置/顺序, jsonb_set()
将其删除。
如果有一种方法可以更新行而不仅仅是删除它,那也会很有帮助。 可能是类似的查询,再次使用jsonb_set()
。
不幸的是,从 Postgres 15 开始,没有 function 返回 JSON 数组元素的 position(目前)。
要删除单个匹配元素:
UPDATE tbl t
SET js = t.js - (SELECT j.ord::int - 1
FROM jsonb_array_elements(t.js) WITH ORDINALITY j(v,ord)
WHERE j.v = '{"ID": "valueb"}'
LIMIT 1)
WHERE t.js @> '[{"ID": "valueb"}]' -- optional
AND jsonb_typeof(t.js) = 'array'; -- optional
此UPDATE
使用与jsonb_array_elements()
相关的子查询。
关于WITH ORDINALITY
:
两个WHERE
子句都是可选的。
使用过滤器t.js @> '[{"ID": "valueb"}]'
来抑制(可能很昂贵!)空更新并充分利用jsonb
列上的现有 GIN 索引
使用过滤器jsonb_typeof(t.js) = 'array'
只抑制来自非数组的错误。
请注意外部过滤器如何包含封闭的数组装饰器[]
,而内部过滤器(在取消嵌套之后)不包含。
要删除所有匹配元素:
UPDATE tbl t
SET js = (SELECT jsonb_agg(j.v)
FROM jsonb_array_elements(t.js) j(v)
WHERE NOT j.v @> '{"ID": "valueb"}')
WHERE t.js @> '[{"ID": "valueb"}]';
第二个查询从剩余元素聚合一个新数组。
这一次,内部过滤器使用@>
而不是=
来允许额外的键。 选择合适的过滤器。
旁白:如果所讨论的数组实际上是嵌套的,则jsonb_set()
可能还有用,这与您的示例不同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.