繁体   English   中英

如何从 JSONB 类型数组中按值删除 object?

[英]How to remove object by value from a JSONB type array?

我想通过 JSONB 数组中唯一的“id”值删除 JSONB object。 我不是编写 SQL 代码的专家,但我设法编写了连接 function。

例如:从下面的数组中删除这个 object。

  {
      "id": "ad26e2be-19fd-4862-8f84-f2f9c87b582e",
      "title": "Wikipedia",
      "links": [
          "https://en.wikipedia.org/1",
          "https://en.wikipedia.org/2"
      ]
    },

架构

CREATE TABLE users (
    url text not null,
    user_id SERIAL PRIMARY KEY,
    name VARCHAR,
    list_of_links jsonb default '[]'
);

list_of_links格式:

[
  {
      "id": "ad26e2be-19fd-4862-8f84-f2f9c87b582e",
      "title": "Wikipedia",
      "links": [
          "https://en.wikipedia.org/1",
          "https://en.wikipedia.org/2"
      ]
    },
      {
      "id": "451ac172-b93e-4158-8e53-8e9031cfbe72",
      "title": "Russian Wikipedia",
      "links": [
          "https://ru.wikipedia.org/wiki/",
          "https://ru.wikipedia.org/wiki/"
      ]
    },
      {
      "id": "818b99c8-479b-4846-ac15-4b2832ec63b5",
      "title": "German Wikipedia",
      "links": [
          "https://de.wikipedia.org/any",
          "https://de.wikipedia.org/any"
      ]
    },
    ...
]

串联 function:

update users set list_of_links=(
     list_of_links || (select *
         from jsonb_array_elements(list_of_links) 
         where value->>'id'='ad26e2be-19fd-4862-8f84-f2f9c87b582e'
          )
  )
where url='test'
returning *
;

您的json数据是结构化的,因此您必须对其进行解压缩,对解压缩的数据进行操作,然后再次重新打包:

SELECT u.url, u.user_id, u.name, 
       jsonb_agg(
           jsonb_build_object('id', l.id, 'title', l.title, 'links', l.links)
       ) as list_of_links
FROM users u
CROSS JOIN LATERAL jsonb_to_recordset(u.list_of_links) AS l(id uuid, title text, links jsonb)
WHERE l.id != 'ad26e2be-19fd-4862-8f84-f2f9c87b582e'::uuid
GROUP BY 1, 2, 3

function jsonb_to_recordset是一个集合返回 function,因此您必须将其用作行源,使用LATERAL子句连接到其原始表,以便list_of_links列可用于要解包的 function。 然后您可以使用WHERE子句删除您不感兴趣的记录,最后通过将记录字段构建为jsonb结构然后将各个记录聚合回数组来重新打包结构。

我是在 JS 上写的,但这对它的工作方式无关紧要。 本质上,它从数组中获取所有项目,然后找到返回索引的匹配 id。 并使用该索引,我使用“-”运算符获取索引并将其从数组中删除。 对不起,如果我的语法不好。

    //req.body is this JSON object
    //{"url":"test", "id": "ad26e2be-19fd-4862-8f84-f2f9c87b582e"}
    var { url, id } = req.body;
    pgPool.query(
        `
                select list_of_links
                from users
                where url=$1;
        `,
        [url],
        (error, result) => {
            //block code executing further if error is true
            if (error) {
                res.json({ status: "failed" });
                return;
            }
            if (result) {
                // this function just returns the index of the array element where the id matches from request's id
                // 0, 1, 2, 3, 4, 5
                var index_of_the_item = result.rows.list_of_links
                    .map(({ id: db_id }, index) =>
                        db_id === id ? index : false
                    )
                    .filter((x) => x !== false)[0];
                //remove the array element by it's index
                pgPool.query(
                    `
                    update users
                    set list_of_links=(
                       list_of_links - $1::int
                    )
                    where url=$2
                    ;
                   `,
                    [index_of_the_item, url], (e, r) => {...}

                );
            }
        }
    );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM