推荐Nodejs下高效存储树到数据库工具库-FlexTree

官网 | English

FlexTreeNodejs下一个基于左右值算法的树结构库,它提供了一种简单的方式来存储和操作树形结构数据。
FlexTree提供了简单而丰富的API让你可以轻松的操作树,如增删改查、遍历、移动、查询等。

主要特性:

  • 基于左右值算法,高效的树结构存储和访问
  • 简单易用的API
  • 丰富的树操作,如增删改查、遍历、移动、查询等
  • 采用TypeScript开发,提供完整友好的类型定义
  • 支持任意数据库存储,如SQLiteMySQLPostgreSQL
  • 95%+的测试覆盖率,保证代码质量
  • 适用Node.js环境

访问官网

了解树模型

在开发Nodejs应用时,当需要在数据库中存储树时,常见的存储结构有以下几种:

  • 邻接列表结构
  • 路径枚举结构
  • 嵌套树结构
  • 闭包表结构

以上算法各有优缺点,应该根据实际的应用场景选择合适的算法。

嵌套树模型(Nested Set Model)也被称为左右值模型,它是一种用于存储树形结构数据的方法,通过两个字段(通常被称为 lftrgt)来表示节点在树中的位置。

在嵌套树模型中,每个节点的lft值都小于其所有子节点的lft值,rgt值都大于其所有子节点的 rgt 值。这样,我们可以通过一个简单的查询来获取一个节点的所有后代,只需要查找lftrgt 值在这个范围内的所有节点即可。

嵌套树模型的左右值分布方式是通过深度优先遍历(Depth-First Search)来确定的。在遍历过程中,每当进入一个节点时,就分配一个 lft 值,每当离开一个节点时,就分配一个 rgt 值。这样,每个节点的 lftrgt 值就形成了一个区间,这个区间内的所有值都对应该节点的子节点。

例如,下面是一个嵌套树模型的例子:

id leftValue rightValue name
1 1 14 root
2 2 9 A
3 10 11 B
4 12 13 C
5 3 4 A-1
6 5 6 A-2
7 7 8 A-3
  • root
    • A
      • A-1
      • A-2
      • A-3
    • B
    • C

快速开始

第1步:安装核心库

首先安装flextree核心库。

ts 复制代码
npm install flextree
// or
yarn add flextree
// or
pnpm add flextree

第2步:配置数据库适配器

接下来,取决于您的应用是如何访问数据库,你需要安装相应的数据库适配器。

本例中,我们使用Sqlite,安装数据库安装flextree-sqlite-adapter

ts 复制代码
npm install flextree-sqlite-adapter
// or
yarn add flextree-sqlite-adapter
// or
pnpm add flextree-sqlite-adapter

flextree-sqlite-adapterflextreesqlite3数据库驱动,基于sqlite3数据库存储。

如果你使用的是MySQLPostgreSQL等数据库,可以安装对应的驱动,如flextree-prima-adapter,或者基于flextree提供的IFlexTreeAdapter自定义驱动。

第3步:创建树表

接下来,我们需要在数据库中创建组织架构树表org

如果你使用的是sqlite数据库,可以使用以下sql语句创建表:

ts 复制代码
import SqliteAdapter from 'flextree-sqlite-adapter';

const sqliteAdapter = new SqliteAdapter("org.db")
await sqliteAdapter.open()
await sqliteAdapter.exec(`
    CREATE TABLE IF NOT EXISTS  org (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name VARCHAR(60),  
        level INTEGER,  
        leftValue INTEGER, 
        rightValue INTEGER,
`)

以上,我们他创建了一个org表,包含以下字段:

字段名 类型 说明
id INTEGER 主键,自增
name VARCHAR(60) 名称
level INTEGER 层级
leftValue INTEGER 左值
rightValue INTEGER 右值

一般情况下,以上字段是必须的,你可以根据实际情况添加其他字段。

提示 :一般情况下,创建表是由应用程序自行完成的,flextree不负责创建表。本节仅演示需要创建的树表结构。

第4步:创建树管理器

接下来,我们创建一个组织架构树管理器OrgManager,用于管理组织架构树。

ts 复制代码
import { FlexTreeManager } from 'flextree';
import SqliteAdapter from 'flextree-sqlite-adapter';

const sqliteAdapter = new SqliteAdapter("org.db")
await sqliteAdapter.open()

const orgManager = new FlexTreeManager("org",{
    adapter: sqliteAdapter     
})

第5步:添加树节点

然后我们就可以开始向组织架构树中添加节点了。

ts 复制代码
// 创建一个根节点
await orgManager.createRoot({
    name: "A公司"
})
// 添加组织架构的一级部门子节点
await orgManager.addNodes([
    { name: "行政中心" },
    { name: "市场中心" },
    { name: "研发中心"} 
])
 
// 添加行政中心的部门子节点.
const node = await orgManager.findNode({name:"行政中心"})
await orgManager.addNodes( [
        { name: "总裁办" },
        { name: "人力资源部" },
        { name: "财务部" },
        { name: "行政部" },
        { name: "法务部" },
        { name: "审计部" }
    ],node)   // 添加为node的子节点

我们可以使用addNodes方法向树中添加节点,addNodes方法支持批量添加节点,支持多种形式的添加子节点。

第6步:访问树

以上我们已经创建了一棵完整的树,接下来我们可以通过两种形式来访问树。

  • 通过FlexTreeManager访问树
  • 通过FlexTree对象访问树

获取节点

ts 复制代码
// 获取所有节点
await orgManager.getNodes() 
// 限定层级获取节点,仅获取第1-3层节点,不包含第4层及以下节点
await orgManager.getNodes(3) 
// 根据id获取节点
await orgManager.getNode(1) 
// 获取树根节点
await orgManager.getRoot()

// 获取name=行政中心的节点
const node = await orgManager.findNode({name:"行政中心"})
// 获取节点<行政中心>的子节点集
await orgManager.getChildren(node)
// 获取节点<行政中心>的所有后代节点集
await orgManager.getDescendants(node)
// 获取节点<行政中心>的所有后代节点集,包括自身
await orgManager.getDescendants(node,{includeSelf:true})
// 获取节点<行政中心>的所有后代节点集,包括限定层级
await orgManager.getDescendants(node,{level:2})
// 获取节点<行政中心>的子节点集,level=1相当于只获取直接子节点
await orgManager.getDescendants(node,{level:1})

// 获取节点<行政中心>的所有祖先节点集
await orgManager.getAncestors(node) 
// 获取节点<行政中心>的父节点
await orgManager.getParent(node) 
// 获取节点<行政中心>的所有兄弟节点集
await orgManager.getSiblings(node)  
// 获取节点<行政中心>的所有兄弟节点集,包括自身
await orgManager.getSiblings(node,{includeSelf:true})  
// 获取节点<行政中心>的前一个兄弟节点
await orgManager.getNextSibling(node)
// 获取节点<行政中心>的后一个兄弟节点
await orgManager.getPrevSibling(node)

查找节点

ts 复制代码
// 查找name=行政中心的节点,只返回第一个满足条件的节点
await orgManager.findNode({name:"行政中心"})
// 查找所有level=1的节点集
await orgManager.findNodes({level:1})

:::warning 提示
FlexTree只提借供简单的查询功能,如果需要更复杂的查询,可以使用数据库的查询功能。

:::

移动节点

ts 复制代码
import { FirstChild, LastChild,PreviousSibling,NextSibling } from 'flextree'
const admin = await orgManager.findNode({name:"行政中心"})
const market = await orgManager.findNode({name:"市场中心"})

// 将行政中心移动到市场中心下,成为其最后一个子节点
await orgManager.move(admin,market)  
await orgManager.move(admin,market,LastChild)  // 与上面等价
// 将行政中心移动到市场中心下,成为其第一个子节点
await orgManager.move(admin,market,FirstChild)
// 将行政中心移动到市场中心前,成为其前一个兄弟节点
await orgManager.move(admin,market,PreviousSibling)
// 将行政中心移动到市场中心后,成为其后一个兄弟节点
await orgManager.move(admin,market,NextSibling)

// 将行政中心上移
await orgManager.moveUpNode(admin)  
// 将行政中心下移
await orgManager.moveDownNode(admin)  

删除节点

ts 复制代码
const admin = await orgManager.findNode({name:"行政中心"})
// 删除行政中心节点以及其所有后代节点
await orgManager.deleteNode(admin)
// 清空树
await orgManager.clear()  

查询节点关系

ts 复制代码
const admin = await orgManager.findNode({name:"行政中心"})
const market = await orgManager.findNode({name:"市场中心"})

// 返回admin节点与market节点的关系
const relation = await getNodeRelation(admin,market)

// relation取值范围
export enum FlexTreeNodeRelation {
    Self = 0,
    Parent = 1,
    Child = 2,
    Siblings = 3,
    Descendants = 4,
    Ancestors = 5,
    DiffTree = 6,
    SameTree = 7,
    SameLevel = 8,
    Unknow = 9,
} 
 

访问官网

推荐

相关推荐
云和数据.ChenGuang1 小时前
Django 应用安装脚本 – 如何将应用添加到 INSTALLED_APPS 设置中 原创
数据库·django·sqlite
woshilys1 小时前
sql server 查询对象的修改时间
运维·数据库·sqlserver
Hacker_LaoYi1 小时前
SQL注入的那些面试题总结
数据库·sql
建投数据2 小时前
建投数据与腾讯云数据库TDSQL完成产品兼容性互认证
数据库·腾讯云
Hacker_LaoYi3 小时前
【渗透技术总结】SQL手工注入总结
数据库·sql
岁月变迁呀3 小时前
Redis梳理
数据库·redis·缓存
独行soc3 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍06-基于子查询的SQL注入(Subquery-Based SQL Injection)
数据库·sql·安全·web安全·漏洞挖掘·hw
燃先生._.4 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
你的微笑,乱了夏天4 小时前
linux centos 7 安装 mongodb7
数据库·mongodb