OPTIONS
翻译或纠错本页面

树结构建模: 物化路径

概述

MongoDB的数据具有 灵活的模式集合 本身没有对文档结构的规则性校验。 但是你建模时所作的决定会影响到应用程序的性能和数据库的处理能力。参见 数据建模理论 以更多的了解一些关于MongoDB数据建模全面介绍。

这篇文章讲述使用一种在节点文档中保存完整的文档关系的方式来实现树结构建模。

范式

物化路径(Materialized Paths) 模式用一个文档保存树结构中的一个节点。除此之外, 这些文档也会保存一个从根节点到当前节点完整路径节点的id组成的一个字符串,称之为 物化路径。虽然 物化路径 本身需要一些额外的字符串处理,但是这种模式在和路径相关的操作方面会更加灵活,如基于部分路径的节点搜索。

让我们看一下下图所示的树形分类结构:

Tree data model for a sample hierarchy of categories.

Tree data model for a sample hierarchy of categories.

下面是一个使用 物化路径 来建模的例子。在节点文档中的 path 字段保存了以逗号为分隔符的路径字符串。

db.categories.insert( { _id: "Books", path: null } )
db.categories.insert( { _id: "Programming", path: ",Books," } )
db.categories.insert( { _id: "Databases", path: ",Books,Programming," } )
db.categories.insert( { _id: "Languages", path: ",Books,Programming," } )
db.categories.insert( { _id: "MongoDB", path: ",Books,Programming,Databases," } )
db.categories.insert( { _id: "dbm", path: ",Books,Programming,Databases," } )
  • 你可以查询整个树的所有节点并按 path 排序:

    db.categories.find().sort( { path: 1 } )
    
  • 你可以在 path 字段上使用正则表达式来查询 Programming 的所有子代节点:

    db.categories.find( { path: /,Programming,/ } )
    
  • 你也可以查询到根节点 Books 的所有子代节点:

    db.categories.find( { path: /^,Books,/ } )
    
  • 你可以在 path 字段上创建索引:

    db.categories.ensureIndex( { path: 1 } )
    

    这个索引对某些查询的性能会有所提高:

    • 如果从根节点开始查询,(e.g. /^,Books,/) , path 字段上的索引会对提高查询性能有显著的作用。

    • 如果查询类似于 Programming 这些非根节点下面的子代节点, (e.g. /,Programming,/)由于这些被查询的节点可能在索引字符串的中部而导致全索引扫描。

      在这种情况下,索引只会在索引所占空间远小于数据所占空间的情况下才会对性能提高有帮助。