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

news2024/11/15 4:32:30

官网 | 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 值就形成了一个区间,这个区间内的所有值都对应该节点的子节点。

在这里插入图片描述

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

idleftValuerightValuename
1114root
229A
31011B
41213C
534A-1
656A-2
778A-3
  • root
    • A
      • A-1
      • A-2
      • A-3
    • B
    • C

快速开始

第1步:安装核心库

首先安装flextree核心库。

npm install flextree
// or
yarn add flextree
// or
pnpm add flextree

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

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

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

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语句创建表:

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表,包含以下字段:

字段名类型说明
idINTEGER主键,自增
nameVARCHAR(60)名称
levelINTEGER层级
leftValueINTEGER左值
rightValueINTEGER右值

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

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

第4步:创建树管理器

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

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步:添加树节点

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

// 创建一个根节点
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对象访问树

获取节点

// 获取所有节点
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)

查找节点

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

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

移动节点

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)  

删除节点

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

查询节点关系


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,
} 
 

访问官网

推荐

  • 全流程一健化React/Vue/Nodejs国际化方案 - VoerkaI18n
  • 无以伦比的React表单开发库 - speedform
  • 终端界面开发增强库 - Logsets
  • 简单的日志输出库 - VoerkaLogger
  • 装饰器开发 - FlexDecorators
  • 有限状态机库 - FlexState
  • 通用函数工具库 - FlexTools
  • 小巧优雅的CSS-IN-JS库 - Styledfc
  • 为JSON文件添加注释的VSCODE插件 - json_comments_extension
  • 开发交互式命令行程序库 - mixed-cli
  • 强大的字符串插值变量处理工具库 - flexvars
  • 前端link调试辅助工具 - yald
  • 异步信号 - asyncsignal
  • 捆绑Vue组件CSS到JS的插件 - vite-plugin-vue-style-bundler
  • 轻量树组件 - LiteTree

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1966461.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AMEYA360:纳芯微高集成单芯片SoC如何高效智能控制车载步进电机?

随着现代汽车电子技术的快速发展&#xff0c;步进电机作为一种精确且可靠的执行元件&#xff0c;在汽车电子系统中的应用日益广泛。为了实现车载步进电机应用的精确控制&#xff0c;纳芯微推出了集成LIN和MOSFET功率级的单芯片车用小电机驱动SoC——NSUC1610&#xff0c;可以帮…

全面掌握VS Code:提升开发效率的终极指南

Visual SCode Visual Studio Code&#xff08;简称VS Code&#xff09;是一款由微软开发的免费、开源且跨平台的代码编辑器。它支持多种编程语言&#xff0c;通过其强大的扩展库&#xff0c;可以满足各种开发需求。本教程将详细介绍如何从安装到高级使用&#xff0c;帮助你充分…

降低Anki对C盘空间占用的四种方法

Anki安装后&#xff0c;笔记中所用到的各种媒体和资源文件默认保存在C盘&#xff0c;例如我的电脑上是保存在“C:\Users\asus\AppData\Roaming\Anki2”&#xff0c;其中asus是我电脑的登录用户名。随着笔记收集越来越多&#xff0c;对C盘的占用也越来越大&#xff0c;因此&…

5问5答!您想了解的数据采集DAQ关键指标都在这里了

1、什么是采样率&#xff0c;它对测量结果有何影响&#xff1f; 采样率是数据采集卡每秒采集数据的次数。采样率对测量结果的准确性有直接影响。如果采样率过低&#xff0c;可能会错过信号的重要部分&#xff0c;导致数据失真。 理论上根据采样定理&#xff0c;采样率应为信…

【C++BFS】802. 找到最终的安全状态

本文涉及知识点 CBFS算法 LeetCode802. 找到最终的安全状态 有一个有 n 个节点的有向图&#xff0c;节点按 0 到 n - 1 编号。图由一个 索引从 0 开始 的 2D 整数数组 graph表示&#xff0c; graph[i]是与节点 i 相邻的节点的整数数组&#xff0c;这意味着从节点 i 到 graph…

【Qwen-Audio部署实战】Qwen-Audio-Chat模型之对话机器人部署测试

系列篇章&#x1f4a5; No.文章1【Qwen部署实战】探索Qwen-7B-Chat&#xff1a;阿里云大型语言模型的对话实践2【Qwen2部署实战】Qwen2初体验&#xff1a;用Transformers打造智能聊天机器人3【Qwen2部署实战】探索Qwen2-7B&#xff1a;通过FastApi框架实现API的部署与调用4【Q…

02.计算器存储器的原理

02.计算器存储器的原理 目录介绍 01.什么是存储器 1.1 了解存储器是什么1.2 存储器类型 02.存储器系统设计 2.1 存储器分层设计2.2 存储器层次结构2.3 高速缓存设计思想2.4 虚拟内存访问内存 03.存储器类型 3.1 按照材质划分3.2 按芯片类型划分3.3 内存 vs CPU3.4 存储器访问…

【Yolov8】实战三:手把手教你使用YOLOv8以及pyqt搭建中医耳穴辅助诊断项目原理及模型部署

摘要 今天&#xff0c;学习RTMPose关键点检测实战。教大家如何安装安装MMDetection和MMPose。 实战项目以三角板关键点检测场景为例&#xff0c;结合OpenMMLab开源目标检测算法库MMDetection、开源关键点检测算法库MMPose、开源模型部署算法库MMDeploy&#xff0c;全面讲解项目…

Spring源码解析(26)之AOP的核心对象创建过程

一、前言 在上一节中我们介绍了在Spring 解析xml配置文件的时候&#xff0c;给我们往容器中生成了很多BeanDefinition&#xff0c;其中最重要的是advice对象&#xff0c;而advice对象最外层是用一个advisor对象包裹起来&#xff0c;而我们的advice对象的创建需要三个参数&#…

|迁移学习| 迁移学习详解及基于pytorch的相关代码实现

&#x1f411; |迁移学习| 迁移学习详解及基于pytorch的相关代码实现 &#x1f411; 文章目录 &#x1f411; |迁移学习| 迁移学习详解及基于pytorch的相关代码实现 &#x1f411;&#x1f411; 前言&#x1f411;&#x1f411; 迁移学习详解&#x1f411;&#x1f411; 迁移学…

第34篇 子程序FINDSUM求和<一>

Q&#xff1a;如何设计汇编语言程序求数组[1:n]的和&#xff1f; A&#xff1a;基本原理&#xff1a;可编写一段实现子程序FINDSUM&#xff0c;子程序中使用一个loop来实现数组的求和运算。子程序FINDSUM的参数N存储在内存中&#xff0c;主程序从该内存中将其读取到一个寄存器…

MES系统如何实现生产任务的自动或辅助调度

MES系统&#xff08;Manufacturing Execution System&#xff0c;制造执行系统&#xff09;通过一系列集成化的功能模块和智能算法&#xff0c;实现生产任务的自动或辅助调度。以下是MES系统实现生产任务自动或辅助调度的具体方式&#xff1a; 1. 生产计划与排程 计划制定&am…

【C++从小白到大牛】类和对象

目录 一、面向过程和面向对象初步认识 二、类的引入 三、类的定义 类的成员函数两种定义方式&#xff1a; 1. 声明和定义全部放在类体中 2. 类声明放在.h文件中&#xff0c;成员函数定义放在.cpp文件中 成员变量命名规则的建议&#xff1a; 四、类的访问限定符 【访问限…

4.2.2、存储管理-段式存储和段页式存储

段式存储 段式存储是指将进程空间分为一个个段,每段也有段号和段内地址,与页式存储不同的是,每段物理大小不同,分段是根据逻辑整体分段的. 地址表示:(段号,段内偏移):其中段内偏移不能超过该段号对应的段长,否则越界错误,而此地址对应的真正内存地址应该是:段号对应的基地址段…

lambdafunctionbind

lambda匿名函数 定义&#xff1a; 捕捉&#xff1a;传值/传引用/mutable 混合捕捉&#xff0c;&#xff1d;表全普通捕捉 即使全部捕捉&#xff0c; 编译器实现时也不一定全部传入&#xff0c; 编译器只会传入要用到的变量 lambda内可使用的变量的范围 lambda内只能用捕捉对…

Linux gcc day 9

cpu是一个只可以执行指令&#xff0c;不是cpu要打印而是我们要打印&#xff0c;然后编译成指令再给cpu&#xff0c;再通过操作系统进行操手 进程状态&#xff1a; 为什么会有这些状态&#xff1f; 进程的多状态&#xff0c;本质都是为了满足未来不同的运行场景 有那些状态&am…

linux系统的检测脚本,用于检查linux的网络配置,包括网络接口状态、IP地址、子网掩码、默认网关、DNS服务器、连通性测试等等

目录 一、要求 二、脚本介绍 1、脚本内容 2、脚本解释 &#xff08;1&#xff09; 检查是否以 root 用户身份运行 &#xff08;2&#xff09;显示脚本标题 &#xff08;3&#xff09;打印主机名 &#xff08;4&#xff09;获取网络接口信息 &#xff08;5&#xff09…

React学习之props(父传子,子传父),Context组件之间的传参。

目录 前言 一、什么时候需要使用props&#xff1f; 二、使用 1.父传子 2.子传父 二、什么时候需要使用Context&#xff1f; 第一步: 第二步使用&#xff1a; 第一种&#xff1a; 第二种&#xff1a; 演示&#xff1a; 总结 前言 React学习笔记记录&#xff0c;pr…

python | TypeError: list indices must be integers or slices, not tuple

python | TypeError: list indices must be integers or slices, not tuple 在Python编程中&#xff0c;TypeError: list indices must be integers or slices, not tuple 是一个常见的错误。此错误通常发生在尝试使用非整数&#xff08;如元组&#xff09;作为列表索引时。本…

WSL和Windows建立TCP通信协议

1.windows配置 首先是windows端&#xff0c;启动TCP服务端&#xff0c;用来监听指定的端口号&#xff0c;其中IP地址可以设置为任意&#xff0c;否则服务器可能无法正常打开。 addrSer.sin_addr.S_un.S_addr INADDR_ANY; recv函数用来接收客户端传输的数据&#xff0c;其中…