当前位置: 首页 > 知识库问答 >
问题:

postgres中的创意json树结构

何超英
2023-03-14

我试图创建一个JSON来表示任意深度和广度的层次结构,例如生物:

CREATE TABLE creatures (
    name text PRIMARY KEY,
    parent text REFERENCES creatures(name)
);

INSERT INTO creatures(name,parent)
VALUES
('amoeba',NULL),
('beetle','amoeba'),
('coelacanth','amoeba'),
('salmon','coelacanth'),
('tuna','coelacanth'),
('lizard','coelacanth'),
('t-rex','lizard'),
('plant',NULL);

我想把它转换成这样的JSON:

[{"name":"amoeba",
  "children": [{"name": "beetle",
                "children": []}, 
               {"name": "coelacanth",
                "children": [{"name": "tuna",
                              "children": []}, 
                             {"name": "salmon",
                              "children": []} 
                             {"name": "lizard",
                              "children": [{"name": "t-rex",
                                            "children": []}]}
                             ]}]},
 {"name": "plant",
  "children": []}]

这在博士后中可行吗?

到目前为止我已经试过了

WITH RECURSIVE r AS
    -- Get all the leaf nodes, group by parent.
    (SELECT parent,
            json_build_object('name', parent, 
                              'children', array_agg(name)) AS json
     FROM creatures c
     WHERE parent NOTNULL
         AND NOT EXISTS
             (SELECT 1
              FROM creatures c2
              WHERE c.name = c2.parent)
     GROUP BY parent
     
     UNION 
     
     -- Recursive term - go one step up towards the top.
     SELECT c.parent,
            json_build_object('name', c.parent, 
                              'children', array_agg(c.name)) AS json
     FROM r
     JOIN creatures c ON r.parent = c.name
     GROUP BY c.parent)
SELECT *
FROM r;

但它失败了

ERROR:  aggregate functions are not allowed in a recursive query's recursive term
LINE 19:                            'children', array_agg(c.name)) AS...

有没有办法解决这个问题,或者其他解决方案可以让我成为我的好树?

共有1个答案

胥康安
2023-03-14

首先,您应该在postgres中使用jsonb格式,而不是json格式,请参阅以下文档:

一般来说,大多数应用程序应该更喜欢将JSON数据存储为jsonb,除非有非常特殊的需求,例如关于对象键排序的遗留假设。。

然后,下面是一种将jsonb转换为文本的方法,因为jsonb替换函数jsonb_集在您的情况下是不可移植的:

CREATE VIEW parent_children (parent, children, root, cond) AS
(   SELECT jsonb_build_object('name', c.parent, 'children', '[]' :: jsonb) :: text AS parent
         , jsonb_agg(jsonb_build_object('name', c.name, 'children', '[]' :: jsonb)) :: text AS children
         , array[c.parent] AS root
         , array[c.parent] AS cond
      FROM creatures AS c
     GROUP BY c.parent
) ;

WITH RECURSIVE list(parent, children, root, cond) AS
(   SELECT children, children, root, cond
      FROM parent_children
     WHERE root = array[NULL]   -- start with the root parents
    UNION
    SELECT p.parent
         , replace(p.children, c.parent, replace(c.parent, '[]', c.children))
         , p.root
         , p.cond || c.cond
      FROM list AS p
     INNER JOIN parent_children AS c
        ON position(c.parent IN p.children) > 0
       AND NOT p.cond @> c.root -- condition to avoid circular path
)
SELECT children :: jsonb
  FROM list AS l
  ORDER BY array_length(cond, 1) DESC
  LIMIT 1 ;

结果是:

[
  {
    "name": "amoeba",
    "children": [
      {
        "name": "beetle",
        "children": []
      },
      {
        "name": "coelacanth",
        "children": [
          {
            "name": "salmon",
            "children": []
          },
          {
            "name": "tuna",
            "children": []
          },
          {
            "name": "lizard",
            "children": [
              {
                "name": "t-rex",
                "children": []
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "name": "plant",
    "children": []
  }
] 
 类似资料:
  • 我在Postgres数据库中有一个分层表,例如,

  • 问题内容: 但是,我仍然无法将csv文件转换为JSON的层次结构。我在stackoverflow上找到的脚本是特定于某个问题的。假设必须对三个变量进行分组: 这将导致这样的JSON文件(据我尝试): 这些必须分组为嵌套结构,例如: 我尝试了该站点上的每个脚本,但是无法创建可以使flare.json这样的通用函数。我可以发布代码,但这就像上面提供的链接一样。因此,我要求一个简单的代码(或可以帮助我的

  • 问题内容: 我正在尝试编写一个可以处理json响应的结构类型 由于键每次都不相同…不同的响应可能包含或多或少的键,不同的键,如您所见,使用50x100返回特定大小的多个图像,我如何创建与此匹配的结构? 我可以这样: 用于单个项目,以及用于特定键的列表。但是包含的结构看起来如何? 就像是: 可能有效,但我无法列举所有可能的图像尺寸响应。另外,Image_Urls末尾没有真正的列表。我希望能够将其直接

  • 问题内容: 我正在尝试在GORM中定义树结构。这是我的模型: 插入似乎可以正常工作,但是当我无法加载具有多个级别和子级别的Tree时。我想我在关系中错过了一些东西:-树应该引用rootLevel(以及可选地引用所有子级别)-一个级别应该引用其父级别,其子级别和全局父树 您能指出我正确的方向以获得这样的树结构吗?谢谢 问题答案: 我最终得到了这个解决方案(感谢朋友): 和 我错过了Tree和Leve

  • 问题内容: 我正在研究一些代码来解析来自HTTP响应的JSON数据。我的代码看起来像这样: 变量中的json 如下所示: 但是,不是零。当我打印出来时,上面写着。是什么原因造成的?JSON似乎有效。此错误与我的自定义结构有关吗? 提前致谢! 问题答案: 所述的结果是一个语法错误在JSON输入(可能丢失,或)。该错误不取决于您解码到的值的类型。 我在操场上使用示例JSON输入运行了代码。它运行没有错

  • 问题内容: 我已经意识到使用SQL数据库(Postgres)是将我的关系数据(24个CSV文件中的40+ GB)移植到具有嵌套结构的 Elasticsearch中的最有效方法之一。但是我仍然对Postgres的JSON输出的格式存在一些问题:1)不需要的换行符(\ n),2)不需要的标题行和3)不需要的日期格式。这是一个基本示例进行演示: 将这些CSV添加到名为Forum的架构并运行以下SQL代码