树结构 (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指向自身,映射到对方的parentparent: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 生成器完成。