广州网站设计成功柚米/常宁seo外包
最近因工作需要接触了一下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)breakcase "初中":gradeId = Number(93)breakcase "高中":gradeId = Number(5)break}switch (courseName) {case "语文":courseId = Number(11)breakcase "数学":courseId = Number(12)breakcase "英语":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() {
}
以上便实现了树形数据的导入,看一下导入结果
使用其他语言按照这样的思路也可以实现数据的初始化导入