跳到主要内容

树结构 (Tree)

树是一种常见的层级结构(菜单、组织架构、分类等)。Aiao 使用“邻接表模型(adjacency-list)”表达树:每个节点记录一个可空的 parentId,并通过自引用关系形成层级。

定义树实体

使用 @TreeEntity 装饰器配合 TreeAdjacencyListEntityBase 基类即可获得树能力:

import { PropertyType, TreeEntity, TreeAdjacencyListEntityBase } from '@aiao/rxdb';

@TreeEntity({
name: 'Menu',
properties: [{ name: 'title', type: PropertyType.string }]
})
export class Menu extends TreeAdjacencyListEntityBase {}

该基类内置两条自关联关系:

  • children: ONE_TO_MANY 指向自身,映射到对方的 parent
  • parent: MANY_TO_ONE 指向自身,nullable: true

因此会自动拥有外键字段 parentId 以及响应式关系属性 children$parent$

关系含义:

  • 一个节点可有 0-N 个子节点
  • 一个节点最多 1 个父节点(根节点无父)

关系属性访问

实例上可通过以下 API 访问和修改关系:

  • parent$: RelationEntityObservable<Menu>
    • 设置父:node.parent$.set(parent);移除父:node.parent$.remove()
  • children$: RelationEntitiesObservable<Menu[]>
    • 添加/移除子:node.children$.add(child) / node.children$.remove(child)
    • 计数:node.children$.count$

也可直接操作外键:child.parentId = parent.id

树查询(仓库 API)

树实体使用 TreeRepository 提供的扩展查询能力:

// 查询所有根节点(仅第一层)
Menu.findRoot({ level: 0 });

// 查询整个树(所有层级)
Menu.findRoot({ level: Number.MAX_SAFE_INTEGER });

// 查询 node 的全部子孙(含自身),限制层级
Menu.findDescendants({ entity: node, level: 3 });

// 查询 node 的全部祖先(含自身),限制层级
Menu.findAncestors({ entity: node, level: 5 });

// 计数接口对应:countRoot/countDescendants/countAncestors

说明:

  • level: 限制递归深度。0 表示不展开(仅自身或仅根),更大值表示更深层级;若需完整树,使用 Number.MAX_SAFE_INTEGER
  • where: 可附加过滤规则(同普通查询的规则构造方式)。

构建与保存示例

const root = new Menu({ title: '根' });
const a = new Menu({ title: 'A' });
const b = new Menu({ title: 'B' });

// 设置层级关系(两种方式等效)
a.parent$.set(root);
b.parentId = root.id;

await rxdb.entityManager.saveMany([root, a, b]);

提示:树以邻接表实现,读写开销与普通表一致;递归查询在本地适配器中由 SQL 生成器完成。