浅谈MongoDB的有序树建模

问题

在业务中,我们常常会用到,例如目录树、部门组织结构等。那么,面对这样的场景,对应的数据表在mongodb中应该如何存储呢?

有序树建模方式

对于树形结构的存储,MongoDB官方给出了5种方式,具体可参考官方文档

  1. 子链接结构
  2. 父链接结构
  3. 祖先队列结构
  4. 物化路径结构
  5. 嵌套结构

那么,我们就主要来学习下可以用来做有序树的前4种建模方式。

1.子链接结构

把子节点的id存储在父节点中。表结构如下:

id children
'china' ['jiangsu','zhejiang']
'jiangsu' ['nanjing','suzhou','wuxi']
'zhejiang' []

优点:
能够快速知道该节点是否有子节点以及有多少子节点。也可通过查询,获取子节点。有利于查询一个节点的子节点。

缺点:
如果子节点过多,父节点就会变得比较大。而且也无法直接获取某个节点下所有的子节点,需要用使用多个查询。

2.父链接结构

把父节点的id存储在子节点中。表结构如下:

id parent
'nanjing' 'jiangsu'
'jiangsu' 'china'
'zhejiang' 'china'

优点:
可通过查询快速获取父子节点。

缺点:
容易产生冗余数据。而且和子链接结构一样,无法直接获取某个节点下所有的子节点,需要用使用多个查询。

3.祖先队列结构

把祖先节点按序存储在子节点中。表结构如下:

id ancestors parent
'nanjing' ['china','jiangsu'] 'jiangsu'
'jiangsu' ['china'] 'china'
'china' [] null

优点:
可通过查询快速获取子节点。也可以通过祖先路径的查询,获取指定节点下的所有子节点,无需多个查询。

缺点:
由于每个节点都存储了所有祖先节点,因此,如果祖先节点发生变化,就会影响所有子节点,所以需要依据具体业务场景,决定是否使用该建模。

4.物化路径结构

把节点路径存储到子节点中。表结构如下:

id path
'china' null
'jiangsu' ',china,'
'nanjing' ',china,jiangsu,'

优点:
同祖先队列结构,且性能略有优势。

缺点:
同祖先队列结构。

总结

以上的几种建模方式,都是非常常用的,在选择建模方式时,要考虑具体业务场景的需求与交互规范,尽量避免由于结构不好导致的批量更新节点、递归多次查询等操作