从 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"}'
            );