新手问题 nestedset 是啥东西?

i5ting · 2013年02月17日 · 最后由 doitian 回复于 2013年02月17日 · 2723 次阅读

木有看懂,求指点 http://threebit.net/tutorials/nestedset/tutorial1.html

For example, below you can see the following:

  • The larger the range between left and right the more children the node has.
  • Right - Left is always negative.
  • MAX(Right)/2 == MAX(*)

Now, that being said the selection of all nodes in an arbitrarily deep nest is done very simply. Generally, this query will be used to feed some other query's in clause or as a constraint for a DML statement.

SELECT
  n0.nid
FROM
  NestedSet n0,
  NestedSet n1
WHERE
    n1.nid = 0
AND n0.lft BETWEEN n1.lft AND n1.rft;

从 sql 看这是一个自关联,难点在 lft 和 rft 这 2 个字段。 通过 lft 和 rft 缩小查询子集,从而达到快速查询的目的。不断的把当前集合变成 n 个嵌入子集,难怪说它有性能优势

嘎嘎,那可以快速获取树的一个算法 不过每次更新都会更新那两个值,查询效率很高

#1 楼 @badboy 我不理解的是 lft 和 rgt 这 2 个字段有啥用

#1 楼 @badboy 不就是典型的自关联么

nestedset

lft 和 rgt 可以确定后代和祖先的范围

对于 2 来说 lft 是 2,rgt 是 11,那所有 lft 在 2-11 之间的都是 2 的后代 对于 8 来说 lft 是 8,rgt 是 9,那 lft <= 8 且 rgt >= 9 的 即 7,2,1 是它的祖先

单纯的用 parent_id 一个字断做树形结构,查询不便,oracle 有 connect by...start with...用法可以查,其他的好像要不然在数据库中存储过程或函数来实现

#4 楼 @kenshin54 不知道我记错没有,oracle 有 connect by...start with... 可以分页吧

#5 楼 @i5ting 我没用它做过分页,主要用来实现树形结构的递归查询

是否自关联不是很重要,不过在一张表里会好很多

简单来说,lft 和 rgt 的值可以用来提高查询的效率 比如按你的那个图来说,你要查树里的 2 这个节点的所有子节点,那就差 lft 大于 2,rgt 小于 11 这样你就可以得到 3、4、5、6、7、8、9、10 这些,都是 2 的子节点,因为 lft 和 rgt 可以作为索引,数值索引查询速度是最快的,所以可以很快定位这些数据

不单查子节点,兄弟节点,父节点都可以很快获取,你可以去深入研究啦,rails 里有一个 gem 支持这个对象的封装,我记不起啥名字了,以前经常用,嘿嘿。

封装完后,你 Class.find(x).children 就能通过 left 和 rgt 获得 3、4、5、6、7、8、9、10

再说白点就是可以让你以前用递归查树结构变成了扁平的查询,一句 sql 搞定

修改少查询多用 nested set,修改比较多的话用 ancestry

需要 登录 后方可回复, 如果你还没有账号请 注册新账号