You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js将Excel数据转JSON并存储到MongoDB失败问题求解

问题原因
  • 异步执行顺序错误:Excel文件读取是流式异步操作,数据库连接也是异步操作。现有代码中调用readFile()后立刻执行insertDb(),此时Excel还未完成读取,finalList是空数组,同时数据库连接大概率还未建立完成,插入操作自然无效,大文件场景下这个问题会更明显。
  • 对象引用错误:singlePerson是全局定义的对象,每次循环处理行数据时都是修改同一个对象的属性,最终finalList中存储的全是同一个对象的引用,所有元素都会被覆盖为最后一行的数据,即使插入成功数据也是错的。
  • MongoDB插入逻辑错误:现有插入代码中new obj(list)是创建单个文档,你传入的list是数据数组,会被当做单个文档的属性存储,不符合需求;且save()是异步方法,没有捕获错误回调,执行失败也不会抛出提示。
  • 大文件内存溢出风险:你把所有Excel行都存在finalList数组里,如果Excel行数极多,会导致内存占用过高甚至进程崩溃,还没到插入步骤程序就已经静默退出。
修复方案

1. 调整异步执行顺序

把插入数据库的操作放到Excel读取完成的end事件回调中,且确保数据库连接成功后再开始读取Excel文件。

2. 修复对象引用问题

每次处理行数据时都重新创建新的singlePerson对象,避免引用覆盖。

3. 修正MongoDB插入逻辑

使用insertMany批量插入数组文档,添加异步错误捕获,方便定位问题。

4. 优化大文件处理

如果Excel文件超过10万行,建议分批插入,每读1000行就插入一次,避免内存占用过高。

修改后代码

excel2.js

const XlsxStreamReader = require("xlsx-stream-reader");
var fs = require('fs');
const config = require('./excelpush.json');
const db = require('./dbmanager.js');

class ExcelReader {
  async readFile() {
    // 先等待数据库连接成功
    await db.connectDb();
    const workBookReader = new XlsxStreamReader();
    let finalList = [];
    // 每批插入1000条,大文件可以调整这个数值
    const BATCH_SIZE = 1000;

    workBookReader.on('error', function (error) {
      throw error;
    })

    workBookReader.on('worksheet', function (workSheetReader) {
      if (workSheetReader.id > 1) {
        workSheetReader.skip();
        return;
      }
      let isFirstLine = true;
      let headerIndex = [];

      workSheetReader.on('row', async function (row) {
        if (isFirstLine) {
          headerIndex = row.values.slice(1);
        } else {
          const rowValues = row.values.slice(1);
          // 每次新建对象,避免引用覆盖
          const singlePerson = {};
          headerIndex.forEach((currentval, index) => {
            singlePerson[currentval] = rowValues[index];
          });
          finalList.push(singlePerson);
          // 达到批量阈值就先插入一次,清空数组释放内存
          if (finalList.length >= BATCH_SIZE) {
            // 暂停流处理,等插入完成再继续,避免背压
            workSheetReader.pause();
            await db.insertDb(finalList);
            finalList = [];
            workSheetReader.resume();
          }
        }
        isFirstLine = false;
      });

      workSheetReader.on('end', async function () {
        // 插入剩余不足一批的数据
        if (finalList.length > 0) {
          await db.insertDb(finalList);
        }
        console.log('所有数据插入完成!');
        // 插入完成后关闭数据库连接
        await db.closeDb();
      });

      workSheetReader.process()
    });

    workBookReader.on('end', function () {
      console.log('Excel文件读取完成!');
    });

    fs.createReadStream(config.filePath).pipe(workBookReader);
  }
}

const excelReader = new ExcelReader();
excelReader.readFile().catch(err => console.log('运行出错:', err));

dbmanager.js

var mongoose = require('mongoose');
const config = require('./db.json');
// 缓存model,避免重复创建
let dataModel = null;

async function connectDb() {
  return new Promise((resolve, reject) => {
    mongoose.connect(`mongodb://${config.dbConfig.host}:${config.dbConfig.port}/${config.dbConfig.dbName}`);
    mongoose.connection.once('open', function () {
      console.log('数据库连接成功');
      // 提前创建model,避免重复生成
      const myschema = new mongoose.Schema({}, { strict: false });
      dataModel = mongoose.model('ExcelData', myschema, config.dbConfig.collectionName);
      resolve();
    }).on('error', function (error) {
      console.log('数据库连接错误:' + error);
      reject(error);
    })
  })
}

async function insertDb(list) {
  try {
    // 批量插入数据
    await dataModel.insertMany(list);
    console.log(`成功插入${list.length}条数据`);
  } catch (err) {
    console.log('插入数据出错:', err);
    throw err;
  }
}

async function closeDb() {
  await mongoose.connection.close();
  console.log('数据库连接已关闭');
}

module.exports = {
  connectDb, insertDb, closeDb
}

现有db.json、excelpush.json配置文件无需修改。

内容的提问来源于stack exchange,提问作者Shakti Swarup Swain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 10:06:04