node实现树形数据的导入

1 篇文章 0 订阅

最近因工作需要接触了一下node,使用过程中遇到了一个需求,需要编写一个脚本,将Excel中的数据插入数据库,但是这个数据是一个树形结构,插入数据库需要插入当前叶子节点的父节点。
在这里插入图片描述
像上图一样,每行都是一个数据,每行的最后一个数据就是要保存的节点,摆上库表结构:
在这里插入图片描述
问题的难点便是导入数据的时候找到节点的父节点id,这里只有路径的中文名称,所以根据中文名称去查询id会遇到名称相同的情况,这样的情况id就不是唯一了,该怎么选择呢?
通过思考,既然给出了中文的路径,也可以用这中文的路径去判断到底应该选哪个父节点呀。
思路:

  • 插入数据如果当前行长度为1说明只有一个一级节点,直接插入,父节点id为0;
  • 当前行长度不为1时是非一级(根)节点,根据父节点名称去查(数据库)父节点id,如果返回一条说明只有一个,将当前节点的父节点设为返回的id即可;
  • 如果返回多个,即根据名称查到多个”父节点“,此时遍历查询到的集合,去递归查询他们的path路径,与当前行读取到的path进行比较,如果相同说明找到当前节点的父节点,进行赋值即可。

下面看一下具体实现过程:


const xlsx = require('node-xlsx');
let sheets = xlsx.parse("./data.xlsx");
let knDB = require("/mysql/KnDb");

async function main() {
    try {
        for (let sheet of sheets) {
            let gradeName = sheet.name.substr(0, 2)
            let courseName = sheet.name.substr(2, 2)
            let gradeId = 0;
            let courseId = 0;
            switch (gradeName) {
                case "小学":
                    gradeId = Number(92)
                    break
                case "初中":
                    gradeId = Number(93)
                    break
                case "高中":
                    gradeId = Number(5)
                    break
            }
            switch (courseName) {
                case "语文":
                    courseId = Number(11)
                    break
                case "数学":
                    courseId = Number(12)
                    break
                case "英语":
                    courseId = Number(13)
                    break
            }
            console.log("年级:" + gradeName + "学科:" + courseName)
            for (let rowId in sheet['data']) {
                let saveValue;
                let obj = new Map();
                if (sheet['data'][rowId].length <= 0) {
                    //空行
                    continue
                }
                let row = sheet['data'][rowId];
                saveValue = row[row.length - 1]
                obj.set("id", Number(rowId) + 1)
                obj.set("path", row) //存放路径
                obj.set("value", saveValue)
                if (row.length <= 1) {
                    //只有一级
                    obj.set("parent", 0)
                } else {
                    //根据父类的名字查询父id的时候可能查到重名的
                    let tempInfo = await knDB.getInfoByName(gradeId,courseId,row[row.length - 2]);
                    if (tempInfo.length > 1) {
                        //存在多个相同名称的
                        for (let t of tempInfo) {
                            let arr = new Array()
                            // arr.push(saveValue)
                            arr = await getPath(t.id, arr);
                            let path = arr.reverse();
                            if (path.toString() === row.slice(0, -1).toString()) {
                                obj.set("parent", t.id)
                                break
                            }
                        }
                    } else {
                        obj.set("parent", tempInfo[0].id)
                    }
                }
                let knowledgePointData = new knowledge();
                knowledgePointData.gradeId = Number(gradeId)
                knowledgePointData.courseId = Number(courseId)
                knowledgePointData.title = obj.get("value")
                knowledgePointData.parentId = Number(obj.get("parent"))
                knowledgePointData.type = Number(0)
                if (knowledgePointData.parentId != Number(0)) {
                    knowledgePointData.type = Number(1)
                }
                knowledgePointData.rootId = Number(0)
                let exist = false;
                exist = await isExist(knowledgePointData);
                //插入之前检查是否已经插入过数据,防止重复插入
                if (exist) {
                    continue
                }
                console.log("新增知识点:" + JSON.stringify(knowledgePointData))
                await knDB.createKnowledgePoint(knowledgePointData)
            }
        }
    } catch (e) {
        console.error(e)
    } finally {
        process.exit()
    }
}

/**
 * 根据id查询路径
 **/
async function getPath(id, path) {
    let knInfo = await knDB.getInfoById(id);
    path.push(knInfo.title)
    if (knInfo.parentId != 0) {
        await getPath(knInfo.parentId, path)
    }
    return path
}

async function isExist(knowledgePointData) {
    let count = await knDB.queryKnowledge(knowledgePointData);
    if (count > 0) {
        return true
    }
    return false
}

function knowledge() {
}

以上便实现了树形数据的导入,看一下导入结果
在这里插入图片描述
使用其他语言按照这样的思路也可以实现数据的初始化导入

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现对Excel树形数据的读取与构建,可以按照以下步骤进行: 1. 导入相关的jar包,如poi、poi-ooxml等,这些jar包可以在Maven仓库中下载。 2. 创建一个Excel文件对象,并获取工作簿对象和工作表对象。 3. 遍历Excel表格中的每一行数据,读取每个单元格的值,并根据单元格的值的情况,构建树形结构。 4. 构建树形结构时,可以创建一个Node类来表示每个节点,节点包含一个值和一个子节点列表。 5. 对于每行数据中的每个单元格,可以通过判断其缩进级别来确定其在树形结构中的层级关系,然后将其添加到相应的节点中。 6. 构建完树形结构后,可以将其保存到一个List或者Map中,以便后续使用。 以下是一个示例代码,仅供参考: ```java import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelTreeReader { public static void main(String[] args) { try { // 读取Excel文件 File file = new File("tree_data.xlsx"); FileInputStream fis = new FileInputStream(file); XSSFWorkbook workbook = new XSSFWorkbook(fis); // 获取第一个工作表 int sheetIndex = 0; Row row; Cell cell; Map<Integer, Node> nodeMap = new HashMap<Integer, Node>(); List<Node> roots = new ArrayList<Node>(); for (int i = 0; i < workbook.getSheetAt(sheetIndex).getLastRowNum(); i++) { row = workbook.getSheetAt(sheetIndex).getRow(i); // 读取缩进级别 int level = 0; while (level < row.getLastCellNum() && row.getCell(level) == null) { level++; } // 读取值 String value = row.getCell(level).getStringCellValue(); // 构建节点 Node node = new Node(value); nodeMap.put(level, node); // 添加到父节点中 if (level == 0) { roots.add(node); } else { Node parent = nodeMap.get(level - 1); parent.addChild(node); } } // 输出树形结构 for (Node root : roots) { System.out.println(root.toString()); } fis.close(); } catch (Exception e) { e.printStackTrace(); } } } class Node { private String value; private List<Node> children; public Node(String value) { this.value = value; this.children = new ArrayList<Node>(); } public void addChild(Node child) { this.children.add(child); } public String toString() { return toString(0); } private String toString(int level) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < level; i++) { sb.append("\t"); } sb.append(value + "\n"); for (Node child : children) { sb.append(child.toString(level + 1)); } return sb.toString(); } } ``` 在这个示例中,我们使用了Apache POI库来读取Excel文件,通过遍历每一行数据来构建树形结构,最终将树形结构输出到控制台。请注意,这个代码只适用于Excel文件中只包含一张表格的情况。如果Excel文件中包含多张表格,需要根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值