最近因工作需要接触了一下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() {
}
以上便实现了树形数据的导入,看一下导入结果
使用其他语言按照这样的思路也可以实现数据的初始化导入