从 cockroachdb 中的 jsonb 数组中删除元素
Delete element from jsonb array in cockaroachdb
我用 jsonb 得到了字段 tags: [{"value": "tag1"}]
我需要做这样的事情update table1 set tags = tags - '{"value": "tag1"}'
- 但是这行不通
我应该执行什么查询来从数组中删除元素?
假设你的table看起来像
CREATE TABLE public.hasjsonb (
id INT8 NOT NULL,
hash JSONB NULL,
CONSTRAINT hasjsonb_pkey PRIMARY KEY (id ASC)
)
您可以使用以下语句执行此操作:
INSERT INTO hasjsonb(id, hash)
(SELECT id,array_to_json(array_remove(array_agg(json_array_elements(hash->'tags')),'{"value": "tag1"}'))
FROM hasjsonb
GROUP BY id
)
ON CONFLICT(id) DO UPDATE SET hash = jsonb_set(hasjsonb.hash, array['tags'], excluded.hash);
此处的实际 json 操作很简单,尽管冗长。我们正在嵌套以下函数:
hash->'tags' -- extract the json value for the "tags" key
json_array_elements -- treat the elements of this json array like rows in a table
array_agg -- just kidding, treat them like a regular SQL array
array_remove -- remove the problematic tag
array_to_json -- convert it back to a json array
棘手的是 json_array_elements
不允许出现在 UPDATE
语句的 SET
部分,所以我们不能只做 SET hash = jsonb_set(hash, array['tags'], <that function chain>
。相反,我的解决方案在允许的 SELECT 语句中使用它,然后将 select 的结果插入回 table。每次尝试插入都会命中 ON CONFLICT 子句,因此我们可以使用 already-computed json 数组来做到这一点 UPDATE set
。
此处的另一种方法可能是使用字符串操作,但这很脆弱,因为您需要担心 json.
中嵌套的对象中出现逗号
如果您通过传递整数静态地知道元素的索引,则可以使用 json_remove_path
删除该元素。
否则,我们可以做一个更简单的子查询来过滤数组元素,然后json_agg
构建一个新数组。
create table t (tags jsonb);
insert into t values ('[{"value": "tag2"}, {"value": "tag1"}]');
然后我们可以删除具有 {"value": "tag1"}
的标签,例如:
UPDATE t
SET tags = (
SELECT json_agg(tag)
FROM (
SELECT *
FROM ROWS FROM (json_array_elements(tags)) AS d (tag)
)
WHERE tag != '{"value": "tag1"}'
);
我用 jsonb 得到了字段 tags: [{"value": "tag1"}]
我需要做这样的事情update table1 set tags = tags - '{"value": "tag1"}'
- 但是这行不通
我应该执行什么查询来从数组中删除元素?
假设你的table看起来像
CREATE TABLE public.hasjsonb (
id INT8 NOT NULL,
hash JSONB NULL,
CONSTRAINT hasjsonb_pkey PRIMARY KEY (id ASC)
)
您可以使用以下语句执行此操作:
INSERT INTO hasjsonb(id, hash)
(SELECT id,array_to_json(array_remove(array_agg(json_array_elements(hash->'tags')),'{"value": "tag1"}'))
FROM hasjsonb
GROUP BY id
)
ON CONFLICT(id) DO UPDATE SET hash = jsonb_set(hasjsonb.hash, array['tags'], excluded.hash);
此处的实际 json 操作很简单,尽管冗长。我们正在嵌套以下函数:
hash->'tags' -- extract the json value for the "tags" key
json_array_elements -- treat the elements of this json array like rows in a table
array_agg -- just kidding, treat them like a regular SQL array
array_remove -- remove the problematic tag
array_to_json -- convert it back to a json array
棘手的是 json_array_elements
不允许出现在 UPDATE
语句的 SET
部分,所以我们不能只做 SET hash = jsonb_set(hash, array['tags'], <that function chain>
。相反,我的解决方案在允许的 SELECT 语句中使用它,然后将 select 的结果插入回 table。每次尝试插入都会命中 ON CONFLICT 子句,因此我们可以使用 already-computed json 数组来做到这一点 UPDATE set
。
此处的另一种方法可能是使用字符串操作,但这很脆弱,因为您需要担心 json.
中嵌套的对象中出现逗号如果您通过传递整数静态地知道元素的索引,则可以使用 json_remove_path
删除该元素。
否则,我们可以做一个更简单的子查询来过滤数组元素,然后json_agg
构建一个新数组。
create table t (tags jsonb);
insert into t values ('[{"value": "tag2"}, {"value": "tag1"}]');
然后我们可以删除具有 {"value": "tag1"}
的标签,例如:
UPDATE t
SET tags = (
SELECT json_agg(tag)
FROM (
SELECT *
FROM ROWS FROM (json_array_elements(tags)) AS d (tag)
)
WHERE tag != '{"value": "tag1"}'
);