如何用async.eachSeries处理Excel转JSON数据插入MongoDB并去重
问题根因
async.eachSeries 第一个入参必须是数组类型,你直接传入的转换结果是「工作表名为键、行数据数组为值」的普通对象,无法被正常遍历。
就算单独取出单个工作表的行数组,也存在两个问题:
- 数组第一项是表头行,从第二项开始才是实际业务数据
- 每行数据的键是A/B/C这类Excel列标识,不是业务需要的实际字段名,无法直接写入MongoDB
实现方案
分三步处理即可:
- 从转换结果中提取目标工作表的行数据
- 基于表头做字段映射,把A/B/C这类列键替换成实际业务字段名,过滤掉表头行,生成标准格式的业务数据数组
- 将处理完成的标准数组传入
async.eachSeries,串行完成重复校验、MongoDB插入逻辑
完整代码示例
const express = require('express'); const upload = require('multer')({ dest: 'uploads/' }); const excelToJson = require('convert-excel-to-json'); const asyncs = require('async'); const app = express(); // 提前引入已定义的MongoDB集合模型,按你的实际路径修改 const Candidate = require('./models/Candidate'); app.post("/", upload.single("excel"), (req, res) => { try { const excelResult = excelToJson({ sourceFile: req.file.path }); // 提取第一个工作表的行数据,固定Sheet1可直接写excelResult.Sheet1 const sheetRows = Object.values(excelResult)[0]; if (!sheetRows || sheetRows.length < 2) { return res.status(400).send('Excel无有效业务数据'); } // 处理字段映射:第一行是表头,后续行按列位置匹配表头生成标准字段 const headerRow = sheetRows[0]; const validData = sheetRows.slice(1).map(row => { const formatItem = {}; Object.keys(row).forEach(colMark => { const fieldName = headerRow[colMark]; formatItem[fieldName] = row[colMark]; }); return formatItem; }); // 串行遍历处理数据 asyncs.eachSeries(validData, async (dataItem) => { // 重复校验:示例以邮箱为唯一维度,可按业务规则调整 const exist = await Candidate.findOne({ Email: dataItem.Email }); if (exist) { console.log(`邮箱${dataItem.Email}对应记录已存在,跳过插入`); return; } // 校验通过插入数据库 await Candidate.create(dataItem); }, (err) => { if (err) { console.error('导入失败', err); return res.status(500).send('数据导入出错'); } res.send('数据全部校验、导入完成'); }) } catch (err) { console.error('接口异常', err); res.status(500).send('服务处理异常'); } })
优化提示
- 多工作表导入场景:遍历
Object.values(excelResult)拿到所有工作表的行数据,统一做字段格式化后合并为一个数组,再传入串行遍历逻辑即可 - 可以直接在调用
excelToJson时加配置,省掉手动写字段映射的逻辑:
const excelResult = excelToJson({ sourceFile: req.file.path, header: { rows: 1 }, // 指定第1行为表头 columnToKey: { '*': '{{columnHeader}}' } // 直接用表头文本作为输出对象的键名 }); // 该配置下取出工作表数组后,直接slice(1)就能拿到字段名正确的业务数据
- 重复校验规则可按业务调整,比如校验手机号、身份证号等唯一字段,或多字段组合唯一。
内容的提问来源于stack exchange,提问作者Ayyan Shaikh
相关产品推荐
相关产品推荐

