OPTIONS
翻译或纠错本页面

树结构建模: 祖先数组

概述

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

这篇文章讲述如何使用在子文档内对父文档及所有祖先文档进行 引用 的方式来对树结构文档建模。

范式

祖先数组 模式用一个文档来表示树的一个节点。每一个文档除了存储节点的信息,同时也存储了对父文档及祖先文档的id值。

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

Tree data model for a sample hierarchy of categories.

Tree data model for a sample hierarchy of categories.

下面是一个使用 祖先数组 的例子。除了 ancestors 字段之外,这些文档还使用 parent 字段保存对父节点的引用:

db.categories.insert( { _id: "MongoDB", ancestors: [ "Books", "Programming", "Databases" ], parent: "Databases" } )
db.categories.insert( { _id: "dbm", ancestors: [ "Books", "Programming", "Databases" ], parent: "Databases" } )
db.categories.insert( { _id: "Databases", ancestors: [ "Books", "Programming" ], parent: "Programming" } )
db.categories.insert( { _id: "Languages", ancestors: [ "Books", "Programming" ], parent: "Programming" } )
db.categories.insert( { _id: "Programming", ancestors: [ "Books" ], parent: "Books" } )
db.categories.insert( { _id: "Books", ancestors: [ ], parent: null } )
  • 查询一个节点所有祖先节点或者从根节点到某个节点的路径的操作很快很方便:

    db.categories.findOne( { _id: "MongoDB" } ).ancestors
    
  • 可以对 ancestors 字段建索引,这样可以快速的按祖先节点查找:

    db.categories.ensureIndex( { ancestors: 1 } )
    
  • 你可以使用 ancestors 字段来查找某个节点所有的子代节点:

    db.categories.find( { ancestors: "Programming" } )
    

祖先数组 模式为需要在树结构里查找某个子树节点以及某个节点的所有祖先节点的场景提供了一个快速有效的方案。对于经常需要操作子树的场景,这是个很好的选择。

祖先数组 模式的效率比起 Materialized Paths 模式来稍微要慢一些,但是使用起来比较容易。