使用JS Promises结合MySQL从扁平表构建组织架构的问题
如何递归获取MySQL扁平表中的多层下属数据
我明白你现在的困扰——想要从扁平的MySQL表中递归获取多层下属,但现有代码只能处理两层,而且Promise的处理也没理顺。别担心,我们一步步来解决这个问题:
首先先指出你现有代码的两个核心问题:
- 缺乏真正的递归逻辑:当前只获取了直接下属的下一层,没法继续深入层级关系
- 存在SQL注入风险:直接把
employerID拼进SQL语句,在生产环境中这是非常危险的操作
1. 先修复SQL注入问题
首先把字符串拼接的SQL改成参数化查询,MySQL驱动支持用?作为占位符,既安全又能避免格式错误:
function getEmployees(employerID) { const query = ` SELECT empName, empID, empManagerID FROM myTable WHERE empManagerID = ? `; return new Promise((resolve, reject) => { con.query(query, [employerID], (err, rows, fields) => { if (err) return reject(err); // 别忘记处理数据库查询错误! resolve(rows); }); }); }
2. 改造函数实现递归嵌套层级
我们需要让函数不仅返回当前经理的直接下属,还要为每个下属递归获取他们的下属,把结构嵌套起来。这里用async/await语法会比纯Promise链式调用更直观,适合处理递归的异步逻辑:
async function getEmployeesWithSubordinates(managerID) { // 第一步:获取当前经理的直接下属 const directEmployees = await getEmployees(managerID); // 第二步:对每个下属递归获取他们的下属 const employeesWithSubordinates = await Promise.all( directEmployees.map(async (employee) => { // 递归调用,拿到当前员工的所有下属 const subordinates = await getEmployeesWithSubordinates(employee.empID); // 返回包含下属层级的员工对象 return { ...employee, subordinates: subordinates }; }) ); return employeesWithSubordinates; }
3. 调用递归函数并写入文件
现在你可以用这个新函数拿到完整的层级结构,再写入reports.json文件:
const fs = require('fs').promises; // 使用Promise版本的fs模块,更贴合异步逻辑 getEmployeesWithSubordinates(125354) .then((fullHierarchy) => { // 把层级对象转成格式化的JSON字符串 const jsonContent = JSON.stringify(fullHierarchy, null, 2); return fs.writeFile('reports.json', jsonContent, 'utf8'); }) .then(() => { console.log('层级数据已成功写入reports.json!'); }) .catch((err) => { console.error('处理过程中出错:', err); });
补充优化建议
如果你的MySQL版本是8.0及以上,其实可以直接用数据库的递归查询(CTE)来一次性获取所有层级的下属,不用在JS里多次发起数据库请求,性能会更好:
WITH RECURSIVE employee_hierarchy AS ( -- 初始查询:获取目标经理的直接下属 SELECT empName, empID, empManagerID FROM myTable WHERE empManagerID = ? UNION ALL -- 递归查询:获取下属的下属 SELECT e.empName, e.empID, e.empManagerID FROM myTable e INNER JOIN employee_hierarchy eh ON e.empManagerID = eh.empID ) SELECT * FROM employee_hierarchy;
你可以把这个SQL封装成函数,一次查询就能拿到所有层级的下属数据,再处理成你需要的嵌套结构。
内容的提问来源于stack exchange,提问作者Stangn99
相关产品推荐
相关产品推荐

