Php 如何使用嵌套集在一个表中存储多个树?

Php 如何使用嵌套集在一个表中存储多个树?,php,tree,doctrine,nested,Php,Tree,Doctrine,Nested,我计划使用orm条令提供的嵌套集特性来提供线程注释。换句话说,我希望在一个表中存储多个独立的树。在我的具体案例中,会有一些实体“新闻”有很多“评论” 我如何告诉条令使用comment.ref_id作为discriminator列?因此,只有具有相同ref_id的节点与一棵树相关。当前,所有树操作都会影响注释表中存储的所有节点。理想的情况是,只有具有给定列名(“ref_id”)的节点将充当一棵树 更新 为了解决这个问题,我想制作一种方法,将许多Hasmanyroot树放在一个表中。 要加载树,必须

我计划使用orm条令提供的嵌套集特性来提供线程注释。换句话说,我希望在一个表中存储多个独立的树。在我的具体案例中,会有一些实体“新闻”有很多“评论”

我如何告诉条令使用comment.ref_id作为discriminator列?因此,只有具有相同ref_id的节点与一棵树相关。当前,所有树操作都会影响注释表中存储的所有节点。理想的情况是,只有具有给定列名(“ref_id”)的节点将充当一棵树

更新 为了解决这个问题,我想制作一种方法,将许多Hasmanyroot树放在一个表中。 要加载树,必须创建如下树:

$category->$treeObject = Doctrine_Core::getTable('Category')->getTree('ref_id',12);
CREATE TABLE category (id BIGINT AUTO_INCREMENT,  
ref_id INT, 
lft INT, 
rgt INT, 
level SMALLINT, 
PRIMARY KEY(id)) ENGINE = INNODB
所有树操作操作都应该包括“WHERE ref_id=12和…”。在我的例子中,你会操纵新闻评论树。因此,数据库更新语句将更少。由于ref_id与新闻相关,ref_id上已经有一个索引,因此它应该运行得相当快

最终解决方案-不属于问题的一部分

通过大量的讨论和反复思考,我提出了以下模式。它包括注释表中列的缩减(去掉了ref_id,root_id现在引用的是根注释而不是新闻)

我觉得这样比较干净。创建新闻需要创建虚拟根节点

        $treeObject = Doctrine_Core::getTable('Comment')->getTree();

        $root = new Comment();
        $root ->content = 'root';
        $root->save();
        $root = $treeObject->createRoot($root);

        $news->setCommentRoot($root);
        $news->save();
最后,您可以在查询“News”时使用左连接来获取根注释,告诉您有多少子级


对于性能问题您可能需要在root\u id-column上手动放置索引。完成。

rootColumnName的值是描述符,因此如果您想使用ref id,您可以执行以下操作:

  actAs:
    NestedSet:
      hasManyRoots: true
      rootColumnName: ref_id
更新:

为了解决这个问题,我想制作一种方法,将许多Hasmanyroot树放在一个表中

您正在尝试重新设计其他功能!:-)

调用
getTree
实际上不会运行查询。。。它只返回实现实例-
Doctrine\u Tree\u NestedSet
。在你询问之前,你有机会得到你想要的

要获得某棵树:

$category->$treeObject = Doctrine_Core::getTable('Category')->getTree()->fetchTree(array('root_id' => 12));
fetchTree的第一个参数是一个选项数组,您可以在这里指定多个选项,包括

  • root\u id
    (将被转换为模式中作为root\u id选项提供的任何内容)
  • 要获取的深度为
    depth
此外,如果需要更复杂的选项,则可以在获取包含所需查询条件的树之前提供基本查询:

// join you news item
$q = Doctrine_Core::getTable('Category')->create('c')
  ->leftJoin('c.News n with n.id = ?', $articleId);

$tree = Doctrine_Core::getTable('Category')->getTree();
$tree->setBaseQuery($q);
$nodes = $tree->fetchTree(array('root_id' => 12));
树的根id应始终指向树中的另一个节点。。。不是外在的东西。通过使用设置基本查询,您可以在整个树上运行联接或提供其他限定条件


但是,
ref_id
不应应用FK约束。根和树是通过树和节点API来管理的,它为您解决了所有这些问题。它将为嵌套集相关列生成的SQL如下:

$category->$treeObject = Doctrine_Core::getTable('Category')->getTree('ref_id',12);
CREATE TABLE category (id BIGINT AUTO_INCREMENT,  
ref_id INT, 
lft INT, 
rgt INT, 
level SMALLINT, 
PRIMARY KEY(id)) ENGINE = INNODB

如果您想省去这些麻烦,请留下这些列定义(如果不合适,除了命名),您将省去这些麻烦。如果您需要重新关联到新闻,请使用与实际嵌套集不关联的单独列/关系。

1)按照您的方式,我必须为每个引用id添加虚拟注释,以仅显示其子项。2) 更新一棵树上的注释仍将影响到目前为止所做的所有其他注释。-我不应该担心这里的表现吗?我对最初的问题写了更多的想法…你的参考不会是虚假的内容。。。查看我的更新。树的根id始终是树上的另一个节点id,而不是与其他节点的关系。所以你需要另一个专栏来为你的新闻添加FK。我试过你的方法。每次我插入新注释时,它都会使用lft和rgt作为标准,对列lft和rgt上的所有注释运行更新。两列都没有索引。有超过30k的评论,这是否仍然表现良好?如果在初始化树时可以通过上面所述的一些附加条件(ref_id),则可以在一个表中存储大量独立的hasManyRoots树。我不喜欢只存储一个hasManyRootsTree和多个hasOneRoot树作为子级。它应该只更新单个树(root_id)的lft和rgt,甚至只更新受更新影响的节点。如果它对表中的每条记录都运行更新,那么您可能没有正确使用HasmanyRoot,或者您的节点插入有问题。如果您发布代码以插入注释,这可能会有所帮助。如果您仍然对可能的性能影响不满意,另一种选择可能是将每个顶级评论及其回复存储为一个单独的树,因为您只需要对评论及其后续回复进行“线程化”。谢谢@prodigitalson的讨论。帮助我了解了很多树。你的答案似乎是对的。我在第一个问题上添加了我最后的想法,只是想让其他人知道。