从所选节点向上构建具有嵌套集的导航

发布于 2024-08-27 23:39:38 字数 1538 浏览 7 评论 0原文

我有以下使用嵌套集与 lft & 的树结构正确值。

node
    node
        node
    node
        node (selected)
        node
node
node
    node

我想构建一个导航,以便树仅展开到所选节点的路径,并且折叠/隐藏不相关的节点。

使用上述方法,树将输出如下:

node
    node
    node
        node (selected)
        node
node
node

使用 php/mysql 可以吗?如果任何 sql 专家可以帮助构建查询,我将非常感激。

我不介意每个级别是否需要一个额外的查询,它最多可能只有 4 或 5 个级别深...

节点表概述:

--
-- Table structure for table `exp_node_tree_1`
--

CREATE TABLE `exp_node_tree_1` (
  `node_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `lft` mediumint(8) unsigned DEFAULT NULL,
  `rgt` mediumint(8) unsigned DEFAULT NULL,
  `moved` tinyint(1) NOT NULL,
  `label` varchar(255) DEFAULT NULL,
  `entry_id` int(10) DEFAULT NULL,
  `template_path` varchar(255) DEFAULT NULL,
  `custom_url` varchar(250) DEFAULT NULL,
  `extra` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`node_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;

--
-- Dumping data for table `exp_node_tree_1`
--

INSERT INTO `exp_node_tree_1` VALUES(1, 1, 12, 0, 'Home', 1, '0', '/', '');
INSERT INTO `exp_node_tree_1` VALUES(5, 10, 11, 0, 'About Us', 2, '4', '', '');
INSERT INTO `exp_node_tree_1` VALUES(6, 6, 9, 0, 'Team', 3, '5', '', '');
INSERT INTO `exp_node_tree_1` VALUES(7, 3, 4, 0, 'Contact Us', 4, '4', '', '');
INSERT INTO `exp_node_tree_1` VALUES(8, 7, 8, 0, 'Awards', 5, '5', '', '');
INSERT INTO `exp_node_tree_1` VALUES(10, 2, 5, 0, 'New Page', 6, '4', '', '');

谢谢!

I have the following tree structure using nested sets with lft & rgt values.

node
    node
        node
    node
        node (selected)
        node
node
node
    node

I'd like to build a navigation so that the tree is expanded, only to the path of the selected node, and non relevant nodes are collapsed/hidden.

Using the above method, the tree would be outputted as follows:

node
    node
    node
        node (selected)
        node
node
node

is this possible using php/mysql? If any sql gurus can help build a query I'd be most appreciative.?

I don't mind if I need an extra query per level, its probably only going to be 4 or 5 levels deep at most...

Overview of the nodes table:

--
-- Table structure for table `exp_node_tree_1`
--

CREATE TABLE `exp_node_tree_1` (
  `node_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `lft` mediumint(8) unsigned DEFAULT NULL,
  `rgt` mediumint(8) unsigned DEFAULT NULL,
  `moved` tinyint(1) NOT NULL,
  `label` varchar(255) DEFAULT NULL,
  `entry_id` int(10) DEFAULT NULL,
  `template_path` varchar(255) DEFAULT NULL,
  `custom_url` varchar(250) DEFAULT NULL,
  `extra` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`node_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;

--
-- Dumping data for table `exp_node_tree_1`
--

INSERT INTO `exp_node_tree_1` VALUES(1, 1, 12, 0, 'Home', 1, '0', '/', '');
INSERT INTO `exp_node_tree_1` VALUES(5, 10, 11, 0, 'About Us', 2, '4', '', '');
INSERT INTO `exp_node_tree_1` VALUES(6, 6, 9, 0, 'Team', 3, '5', '', '');
INSERT INTO `exp_node_tree_1` VALUES(7, 3, 4, 0, 'Contact Us', 4, '4', '', '');
INSERT INTO `exp_node_tree_1` VALUES(8, 7, 8, 0, 'Awards', 5, '5', '', '');
INSERT INTO `exp_node_tree_1` VALUES(10, 2, 5, 0, 'New Page', 6, '4', '', '');

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

束缚m 2024-09-03 23:39:38

鉴于您没有任何不是根节点的直接子节点的兄弟节点,您的示例数据使其变得困难,但我将使用那里的内容:)

我认为您需要两个 SQL 调用- 一种用于获取包含所选节点的左/右值的所有节点,另一种用于使用上一次调用中的“父”左/右值来获取所选节点的同级节点,

例如
抓取包含目标节点左/右值的所有节点

SELECT e.* FROM exp_node_tree_1 as e, (SELECT lft, rgt FROM exp_node_tree_1 WHERE node_id = ?) AS tbl WHERE (e.lft < tbl.lft) and (e.rgt > tbl.rgt) ORDER BY e.lft ASC

替换?与所选节点的node_id。这将返回所选节点的所有祖先,从顶层开始一直到所选节点的直接父级

第二个查询(同级)可以通过两种方式完成,具体取决于您是否想使用已经的 lft / rgt 值返回(例如从 PHP 获取值),或者您是否想要在 SQL 中完成繁重的工作。在 SQL 中执行此操作意味着查询更加复杂,但除了所选节点的 id 之外,您不需要任何数据

使用所选节点父节点的 PHP 值(在上一个查询中返回)

SELECT * FROM `exp_node_tree_1` WHERE (lft > ?) AND (rgt < ?) ORDER BY lft ASC

替换第一个 ?与父级的 lft 值,第二个 ?与父节点的 rgt 值

第二种方法仅使用所选节点的node_id

select s.* FROM exp_node_tree_1 as s, (SELECT e.lft, e.rgt FROM exp_node_tree_1 as e, (SELECT lft, rgt FROM exp_node_tree_1 WHERE node_id = ?) AS tbl WHERE (e.lft < tbl.lft) and (e.rgt > tbl.rgt) ORDER BY e.lft DESC LIMIT 1) as parent WHERE (s.lft > parent.lft) AND (s.rgt < parent.rgt) ORDER BY s.lft ASC

就像我说的 - 有点复杂。替换?与所选节点的node_id

希望这有帮助!

Your sample data makes it hard, given that you don't have any sibling-nodes that aren't direct children of the root node, but I'll work with what's there :)

I'd think you'll need two SQL calls - one to grab all the nodes that contain the left/right values of your selected node, and one to use the 'parent' left/right values from the previous call to grab the siblings of your selected node

e.g.
Grab all the nodes that contain the left/right values of your target node

SELECT e.* FROM exp_node_tree_1 as e, (SELECT lft, rgt FROM exp_node_tree_1 WHERE node_id = ?) AS tbl WHERE (e.lft < tbl.lft) and (e.rgt > tbl.rgt) ORDER BY e.lft ASC

Replace the ? with the node_id of the selected node. This returns all ancestors of your selected node, starting at the top-level and working down to the direct parent of your selected node

The second query (siblings) can be done two ways, depending if you want to use the lft / rgt values already returned (e.g. grabbing the values from PHP), or whether you want to do the heavy lifting in SQL. Doing it in SQL means the query is more complex, but you don't need any data other than the selected node's id

Using PHP values from the selected node's parents (returned in the previous query)

SELECT * FROM `exp_node_tree_1` WHERE (lft > ?) AND (rgt < ?) ORDER BY lft ASC

Replace the first ? with the lft value of the parent, and the second ? with the rgt value of the parent

The second method only uses the node_id of the selected node

select s.* FROM exp_node_tree_1 as s, (SELECT e.lft, e.rgt FROM exp_node_tree_1 as e, (SELECT lft, rgt FROM exp_node_tree_1 WHERE node_id = ?) AS tbl WHERE (e.lft < tbl.lft) and (e.rgt > tbl.rgt) ORDER BY e.lft DESC LIMIT 1) as parent WHERE (s.lft > parent.lft) AND (s.rgt < parent.rgt) ORDER BY s.lft ASC

Like I said - a bit more complex. Replace the ? with the selected node's node_id

Hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文