【发布时间】:2019-01-27 03:47:41
【问题描述】:
tl;dr -- 有没有办法从 postgres 中的 jsonb 对象获取值作为 jsonb_array?
尝试在 postgres 中使用递归 cte 来展平任意深度的树结构,如下所示:
{
"type": "foo",
"properties": {...},
"children": [
"type": "bar",
"properties": {...},
"children": [
"type": "multivariate",
"variants": {
"arbitrary-name": {
properties: {...},
children: [...],
},
"some-other-name": {
properties: {...},
children: [...],
},
"another": {
properties: {...},
children: [...],
}
}
]
]
}
通常关注this post,但是我一直在处理type: "multivariate" 节点,我真正想要的基本上是jsonb_agg(jsonb_object_values(json_object -> 'variants'))
更新:
抱歉,我显然应该包含我尝试过的查询:
WITH RECURSIVE tree_nodes (id, json_element) AS (
-- non recursive term
SELECT
id, node
FROM trees
UNION
-- recursive term
SELECT
id,
CASE
WHEN jsonb_typeof(json_element) = 'array'
THEN jsonb_array_elements(json_element)
WHEN jsonb_exists(json_element, 'children')
THEN jsonb_array_elements(json_element -> 'children')
WHEN jsonb_exists(json_element, 'variants')
THEN (select jsonb_agg(element.value) from jsonb_each(json_element -> 'variants') as element)
END AS json_element
FROM
tree_nodes
WHERE
jsonb_typeof(json_element) = 'array' OR jsonb_typeof(json_element) = 'object'
)
select * from tree_nodes;
架构只是一个 id 和一个 jsonb node 列
此查询给出错误:
ERROR: set-returning functions are not allowed in CASE
LINE 16: THEN jsonb_array_elements(json_element -> 'children')
^
HINT: You might be able to move the set-returning function into a LATERAL FROM item.
我只想要Object.values(json_element -> 'variants') ????
更新 2:
再读一遍后,我意识到这是一个问题,因为我使用的是最新版本的 PostgreSQL (10.3),它显然不再允许从 CASE 语句返回一个集合,这有点像让这种树扁平化方法能够正常工作。在 PostgreSQL 的最新版本中可能有一些方法可以实现相同的目标,但我不知道该怎么做。
【问题讨论】:
-
如果可以的话,发布一些您尝试过的架构和查询。
-
你想要一个数组中的'variants'的三个子元素?还是想要数组中的“属性”/“子项”对?
-
天哪,现在我在吃完晚饭后再次查看它,我意识到不是
variants导致了问题,而是children的数组。我列出的文章中的示例在 Postgres 10 中根本不可能吗?? -
@S-Man 我希望节点展平以便返回具有列
tree_id和node列(节点是具有type、properties和children属性的 jsonb 对象) -
@Steve 请提供预期输出的样本。应该展平哪个部分以及变体会发生什么情况?
标签: postgresql recursion