Skip to content

修复树

FlexTree 基于左右值算法,树结构的完整性严格依赖每一个节点的leftValuerightValue的正确性。

由于直接操作数据表、写操作异常中断或其他外部原因,可能导致节点的左右值或层级被破坏。此时正常的查询、遍历等操作会返回错误的结果。

FlexTreeManager 提供了repair方法用于修复被破坏的树结构;此外flextree还导出了纯函数repairTree,可脱离数据库直接对节点数组进行修复。

提示

repair是一个写操作,其内部会自动在write与数据库事务中执行,因此无需手动包裹在write

修复整棵树

调用manager.repair()即可修复当前管理器所管理的树。

ts
import { FlexTreeManager } from 'flextree'
import SqliteAdapter from 'flextree-sqlite-adapter'

const tree = new FlexTreeManager('tree', {
    adapter: new SqliteAdapter(),
})

await tree.repair()
  • 说明

    • repair会直接读取表中所有节点的idlevelleftValuerightValue(由于树可能已被破坏,不能依赖正常的查询方法),重建结构后仅将发生变化的节点写回数据库
    • 在单表多树场景下,读取与更新都会自动限定在当前treeId范围内,不会跨树影响。

修复算法

repair基于节点的level(层级)信息重建树结构,核心步骤如下:

  1. leftValue排序,保留节点原有的先后顺序;
  2. 借助栈、基于level判断父子关系,重新分配连续leftValue/rightValue,确保所有值落在1..2N区间内且完整无缺口;
  3. 规范化level:根节点为0,每层递增1,自动修复跳级(如0 → 3 → 7会被规范为0 → 1 → 2);
  4. 修复后自动进行完整性校验,校验失败会抛出异常而非返回错误数据。

例如,一棵左右值被破坏的树:

  • Root
    • A
      • A1
      • A2
    • B

执行repair后,所有节点的leftValue/rightValue会被重新分配为连续且正确的值,层级也会被规范化。

repairTree 纯函数

如果已经持有节点数组(例如来自其他数据源或备份),可以使用导出的repairTree纯函数直接修复,无需经过数据库。

ts
import { repairTree } from 'flextree'

const repaired = repairTree(nodes, {
    keyFields: { /* 自定义字段名,可选 */ },
    treeId: 1, // 多树表时注入 treeId,可选
})
  • 参数
参数 类型 默认 描述
nodes Record<string, any>[] 待修复的节点数组(不会被修改)
options.keyFields CustomTreeKeyFields 默认字段 自定义关键字段名
options.treeId any 多树表时注入到结果节点的treeId
  • 说明

    • repairTree是纯函数,不会修改入参nodes,返回修复并按leftValue排序后的新节点数组。
    • 值发生变化的节点会附带_level/_leftValue/_rightValue元数据,记录修复前的原值,便于对比。

提示

修复前可以使用校验方法检测树结构是否被破坏,修复后可再次校验以确认完整性。