目前常见的树形结构数据库存储方案有以下四种,但是在处理无限深度、海量数据的树结构时,都存在一些问题:
1)Adjacency List(邻接表):每个节点仅记录父节点主键。优点是简单,缺点是访问子树需要递归遍历,对数据库压力大(即使是支持递归SQL的数据库)。
2)Path Enumerations( 路径枚举):用一个字符串记录当前节点所在路径。优点是查询方便,缺点是占用空间大,查询需要使用like模糊方法,效率低,插入新记录时要手工更改此节点以下所有路径,维护不便。
3)Closure Table(闭包表):专门一张表维护Path,缺点是占用空间大,操作不直观。
4)Nested Sets (嵌套集):记录左值和右值,优点是查询子树无需递归,缺点是非常复杂、难操作。

本文介绍的方案原理详见"基于前序遍历的无递归的树形结构的数据库表设计" ,在这里我给它名叫“海底捞算法”,这个比较形象,因为它要求插入一行EndTag在表格的底部(具有最大行号)。本文是这种算法在MongoDB中的实现示例。

这个算法的优点是简单,支持无限深度树、查询子树时无需递归、删除节点和偶尔插入节点时可以做到无需修改其它记录(行号跳号设计),从以下示例代码中就可以看出这种方案的简洁性:

Books
|-Programning
| |-Languages
| |-Databases
| | |-MongoDB
| | | |-MongoTree
| | |-dbm
|-Arts db.book.insert({ _id: “Books”, line:1000,level:1} );
db.book.insert({ _id: “Programming”, line:2000,level:2} );
db.book.insert({ _id: “Languages”, line:3000,level:3} );
db.book.insert({ _id: “Databases”, line:4000,level:3} );
db.book.insert({ _id: “MongoDB”, line:5000,level:4} );
db.book.insert({ _id: “MongoTree”, line:6000,level:5} );
db.book.insert({ _id: “dbm”, line:7000,level:4} );
db.book.insert({ _id: “Arts”, line:8000,level:2} );
db.book.insert({ _id: “EndTag”, line:10000,level:0} ); //查询节点 “Databases”下的所有子节点:
db.book.createIndex( {line:1});
var node = db.book.findOne( { _id: “Databases” } );
var next=db.book.findOne( { $and: [ {line: {$gt:node.line}}, {level:{$lte: node.level }}] } );
db.book.find( {$and: [{line: { $gt: node.line }}, {line: { $lt: next.line }}] } ); //插入一个新节点,不需要对其它行号执行加1操作,因为这个示例中行号是跳号设计的,节点可以插入在两个行号的中间
db.book.insert({ _id: “MySql”, line:6500,level:5} ); //删除一个节点,真接删就可以了
db.book.remove({ _id: “Languages”} );

最新文章

  1. [BZOJ2072][POI2004] MOS过桥
  2. 谈谈基于OAuth 2.0的第三方认证 [下篇]
  3. 关于eclispe保存代码自动格式化的设置
  4. Finger Gestures 3.1
  5. NABCD分析java音乐播放器
  6. text-overflow 与 word-wrap:设置使用一个省略标记...标示对象内文本的溢出。
  7. Goolg Chrome 插件开发--Hello world
  8. L006-oldboy-mysql-dba-lesson06
  9. I2c串行总线组成及其工作原理
  10. 编写一个Java应用程序,该程序包括3个类:Monkey类、People类和主类 E。要求: (1) Monkey类中有个构造方法:Monkey (String s),并且有个public void speak() 方法,在speak方法中输出“咿咿呀呀......”的信息。 (2)People类是Monkey类的子类,在People类中重写方法speak(),在speak方法 中输出“小样的,不
  11. Show username instead of "System Account" in SharePoint 2010
  12. swift3.0 扩展、协议(4)
  13. 安装Dubbo管理控制台
  14. opengl启动过程
  15. JMeter常见错误解决方法
  16. MRO
  17. 用户认证--------------auth模块
  18. 在Android上启用Kiosk模式
  19. python工具 - 批量文件重命名
  20. 使用WebService与Oracle EBS进行集成

热门文章

  1. 深入浅出SharePoint2010——请假系统无代码篇之工作流设计
  2. linux下的线程学习(二)
  3. Hdfs&MapReduce测试
  4. Chapter 5 Order Inversion Pattern
  5. Java(Android)编程思想笔记03:在Android开发中使用MVP模式
  6. Ubuntu root 密码忘记-恢复
  7. BZOJ2208:[JSOI2010]连通数(DFS)
  8. 【LGP5108】仰望半月的夜空
  9. 【[SDOI2013]泉】
  10. 【[NOI2009]管道取珠】