Node.js读取CSV转JSON异步循环更新MongoDB的实现问题
用Node.js读取CSV并批量更新MongoDB数据的异步实现方案
我尝试用Node.js把CSV文件转成JSON数组后更新MongoDB,但循环处理时遇到Promise相关问题。现有代码能不能通过循环完成数据库更新?如果不行,该怎么用Node.js异步实现?
现有代码的核心问题
你的代码无法正常完成更新,主要是这几个问题:
map函数里直接用await,但map不会等待异步操作完成,导致所有更新请求同时发起,既无法保证执行顺序,还可能引发MongoDB连接池溢出findOneAndUpdate缺少匹配条件和更新字段,根本没法完成有效更新result变量定义在map内部,外部console.log(result)会直接报错
可行的异步实现方案
针对批量更新场景,有两种靠谱的异步处理方式,按需选择:
方案1:串行处理(适合小数据量)
用for...of循环逐个处理,每次等待当前更新完成后再执行下一个,逻辑简单易调试。
方案2:并行控制(适合大数据量)
用Promise.all()分批处理,控制每批并发数,避免给MongoDB造成过大压力。
修改后的完整代码
import csvtojson from "csvtojson"; import { MongoClient } from "mongodb"; const csvFilePath = "./data.csv"; const uri = "mongodb://localhost:27017"; // 列出数据库(保留原有逻辑) async function listDatabases(client) { const databasesList = await client.db().admin().listDatabases(); console.log("Databases:"); databasesList.databases.forEach((db) => console.log(` - ${db.name}`)); } async function main() { const client = new MongoClient(uri); try { await client.connect(); await listDatabases(client); } catch (e) { console.error(e); } finally { await client.close(); } } main().catch(console.error); async function updateData() { const client = new MongoClient(uri); try { // 1. 读取CSV并转成JSON数组 const csvData = await csvtojson().fromFile(csvFilePath); console.log(`读取到 ${csvData.length} 条待更新数据`); // 2. 连接MongoDB await client.connect(); const db = client.db("nabatiform"); const usersCollection = db.collection("users"); // ========== 方案1:串行处理 ========== for (const item of csvData) { // 以NIK作为唯一匹配条件(确保更新正确的用户) const filter = { NIK: item.NIK }; // 要更新的字段(注意CSV的Plant是大写,MongoDB里是小写plant,统一字段名) const updateDoc = { $set: { fullname: item.fullname, Group_Shift: item.Group_Shift, plant: item.Plant, Gedung_Zona: item.Gedung_Zona, Sector: item.Sector, SPV: item.SPV, updatedAt: Date.now() // 更新时间戳 } }; // 可选:如果没匹配到文档,是否插入新文档(按需设置为true/false) const options = { upsert: false }; const result = await usersCollection.findOneAndUpdate(filter, updateDoc, options); console.log(`NIK ${item.NIK}:`, result.matchedCount ? "更新成功" : "未找到匹配文档"); } // ========== 方案2:并行分批处理(注释掉方案1后启用) ========== // const batchSize = 10; // 每批处理10条,可根据服务器配置调整 // for (let i = 0; i < csvData.length; i += batchSize) { // const batch = csvData.slice(i, i + batchSize); // await Promise.all(batch.map(async (item) => { // const filter = { NIK: item.NIK }; // const updateDoc = { // $set: { // fullname: item.fullname, // Group_Shift: item.Group_Shift, // plant: item.Plant, // Gedung_Zona: item.Gedung_Zona, // Sector: item.Sector, // SPV: item.SPV, // updatedAt: Date.now() // } // }; // return usersCollection.findOneAndUpdate(filter, updateDoc, { upsert: false }); // })); // console.log(`完成第 ${Math.floor(i/batchSize)+1} 批更新`); // } } catch (e) { console.error("更新失败:", e); } finally { await client.close(); console.log("数据库连接已关闭"); } } updateData().catch(console.error);
CSV转换后的JSON结果
[ { "NIK": "22000028", "Plant": "Majalasgka", "fullname": "FERI FsaYAH", "Group_Shift": "R1", "Gedung_Zona": "Gas A", "Sector": "SEKTOas 08", "SPV": "TasI SUasWATI" }, { "NIK": "22000330", "Plant": "Majaaka", "fullname": "AYasdMAYANTI", "Group_Shift": "NSHT", "Gedung_Zona": "GEDU", "Sector": "SE-08", "SPV": "TI" } ]
MongoDB文档示例
{ "_id": { "$oid": "6369b17b11e02557349d8de5" }, "fullname": "EGA PERMANA SAPUTRA", "password": "$2b$10$TuKKwzIxmqvnJfR8LRV/zu1s.Gqpt4yANLAcNNFQ6pqTuLL82.00q", "NIK": "17000691", "status": "active", "department": "Prodaucasdfation", "position": "Foreasdman", "Group_Shift": "R1", "role": "user", "__v": 0, "createdAt": 1667871099, "updatedAt": 1669025651, "userInformation": {}, "plant": "Majasangka" }
内容的提问来源于stack exchange,提问作者JS24
相关产品推荐
相关产品推荐

