我试图查看是否有办法将平面列表转换为rethinkdb中的分层树。
鉴于此表:
nodes
------
-id
-name
-parent
我可以使用r.db('app').table('nodes')
查询所有内容并获得一个平面列表:
[
{name: "one", id: "1"}
{name: "two", id: "2", parent: "1"}
{name: "three", id: "3", parent: "2"}
]
但我真的很喜欢以层次结构返回数据的查询:
[
{
name: "one",
id: "1",
children: [
{
name: "two",
id: "2",
children: [
{name: "three", id: "3"}
]
}
]
}
]
这可以在rethinkdb中使用吗? Postgres对此进行了WITH RECURSIVE次查询。目前我正在应用层进行转换,但它变得越来越复杂 - 例如,为了获取单个节点,我还必须获取所有节点,递归地添加其后代,并仅返回所请求的节点。无论如何,如果可能的话,我很乐意在rethinkdb中找到一种方法。谢谢!
答案 0 :(得分:1)
遗憾的是,在RethinkDB中没有简单的方法可以做到这一点。您对该架构的依恋程度如何? (如果答案是“不是很”,那么你需要在这张桌子上快速查询什么?)
答案 1 :(得分:0)
如果你想要一个有限的嵌套子集,你可以在表本身上使用连接/子查询
首先在父
上创建一个索引r.db('app').table('nodes').indexCreate("parent")
然后,如果你只想要一个级别的孩子,你可以做
r.db('app').table('nodes').merge(function(node) {
return {
r.db('app').table('nodes').getAll(node("id"), {index: "parent"}).coerceTo("ARRAY")
}
})
如果您需要任意数量的级别,这是不可能的,那是因为如果您有循环引用,事情就会破裂。
答案 2 :(得分:0)
我最近遇到了同样的问题。还想为每个节点引入children
属性。但这并不好,因为每个新节点的创建/删除都会导致2个db写操作。
所以,我提出的解决方案如下:
group
/ ungroup
聚合方法
例如,在Node/Express
后端:
r.db('app').table('nodes').group('parent').ungroup().run(dbConnection)
.then( groupedByParent => {
// make a temp hashmap as grouped data from RethinkDB comes as Array
// of groups.
const parentsMap = groupedByParent.reduce( (result, groupData) => {
// each generated group has `group` prop which is the parent id in
// our case and `reduction` prop which is the Array of all nodes
// with this parent id
const { group, reduction } = groupData
// read prerequisites at the end of this post to better understand
// below contruction
const parentId = group === null ? 'roots' : group
result[parentId] = reduction
return result
}, {})
// construct a final tree. parentMap will make it easier to get all
// children of particular node
const tree = parentsMap.roots.map(function mapper(node) {
// do nothing if this node doesn't have children
const children = parentsMap[node.id]
if (typeof children === 'undefined') return node;
// else recursively iterate over children to grab all sub-children
node.children = children.map(mapper)
return node
});
})
前提条件:要使其正常工作,所有节点必须具有parent
属性(不得丢失),因此如果节点没有父节点parent
属性将等于null
注意:我使用ungroup
并仅为方便起见准备最终树 - 使用标准JavaScript方法轻松操作分组数据,而不是使用RethinkDB的特殊控制结构。我想有可能只使用RethinkDB的指令构建完整的树(例如以某种方式使用fold
方法)
如果在节点表上创建group
索引,parent
也会更快。