Database design 数据库分层数据

Database design 数据库分层数据,database-design,recursion,rethinkdb,Database Design,Recursion,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"} ] 但我确实希望查询以层次结构返回数据: [ {

我想看看是否有一种方法可以将平面列表转换为数据库中的层次树

鉴于此表:

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"}
        ]
      }
    ]
  }
]

这在DB中可能吗?Postgres对此有疑问。目前,我正在应用层进行转换,但它变得越来越复杂——例如,要获取单个节点,我还必须获取所有节点,递归地添加其子节点,然后仅返回请求的节点。不管怎么说,如果可能的话,我很想找到一种方法来解决这个问题。谢谢

不幸的是,在数据库中没有简单的方法可以做到这一点。您对该模式的依附程度如何?(如果答案是“不太”,那么需要在此表上快速执行哪些查询?

如果需要一组嵌套子项,可以在表本身上使用联接/子查询

首先在父对象上创建索引

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 db的写入操作

因此,我提出的解决方案如下:

  • 我使用DB api的
    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
      });
    })
    
    先决条件:要使其正常工作,所有节点都必须具有
    父节点
    属性(它不能丢失),因此如果节点没有父节点,则其
    父节点
    属性将等于
    null

    注意:我在这里使用
    解组
    并准备最终的树只是为了方便-使用标准JavaScript方法而不是RejectDB的特殊控制结构轻松地操纵分组数据。我想只需要DB的指令就可以构建完整的树(例如,以某种方式使用
    fold
    方法)


    另外,如果您在nodes表上创建一个
    父索引,则
    group
    ing将更快。

    在RejectionDB中有这样做的方法,但它们非常复杂,不具有线程安全性,并且不是您希望在生产中使用的那种方法。如果有一个引人注目的用例,我们可以为此添加明确的支持。你能描述一下你为什么要找这样的功能吗?(请随时给我发电子邮件--slava@rethinkdb.com)谢谢你的回复,斯拉瓦。这种递归查询功能将有助于任何层次化数据用例,在这些用例中,您通常必须生成毛茸茸的应用程序逻辑或转向图形数据库。在我的例子中,我正在构建一个思维导图应用程序,其中每个节点可以有n个子节点。我绝对喜欢postgres的强大功能,但我更喜欢RejectDB的灵活模式,因为节点可以有不同的字段(描述、图片、检查表、标记等)。思想?更多关于递归查询的信息:啊,我明白了。也许图形数据库是更好的选择?我将考虑引入方便的递归功能,但这可能需要一段时间。太棒了,随时通知我!我也想要这个功能。目前,neo4j是我选择的数据库,但对于大型树来说,它无法扩展。我肯定会接受其他模式选项。也许在每个节点中都有一个ID的“子”数组会使这更容易一些。需要快速执行的查询包括:-获取一个节点及其所有子节点-更新一个节点可以将其作为一个包含嵌套文档的大型文档来完成,但这似乎并不理想。为此,这无疑是获取第一组子节点的好方法。现在,如果有一种方法可以像在postgres中那样递归地实现这一点。。。