Node.js使用Mongoose操作MongoDB:3000条数据增查耗时过长
优化方案
原代码的核心问题是单条循环执行数据库查询与写入,3000条数据会产生3000次查询+N次单条写入,IO开销极大,以下是针对性优化手段:
1. 批量查询已存在记录,消除重复查询
先一次性提取所有待处理数据的(name, network)组合,通过一次查询获取所有已存在的记录,后续在内存中判断是否需要插入,避免3000次重复数据库查询:
// 提取所有待校验的(name, network)组合 const queryConditions = data.map(item => ({ name: item.coin, network: item.network })); // 一次性查询所有已存在的记录 const existingCoins = await Coin.find({ $or: queryConditions }); // 将已存在的组合存入Set,方便快速判断 const existingPairs = new Set(); existingCoins.forEach(coin => { existingPairs.add(`${coin.name}-${coin.network}`); });
2. 批量插入新数据,减少写入次数
将所有需要插入的新文档收集起来,通过insertMany一次性写入数据库,替代单条save操作,大幅降低数据库写入IO:
// 筛选出不存在的记录,构造插入文档 const newCoinDocs = data.filter(item => { const pairKey = `${item.coin}-${item.network}`; return !existingPairs.has(pairKey); }).map(item => ({ _id: new mongoose.Types.ObjectId(), name: item.coin, title: item.name, network: item.network, contract: item.contract })); // 批量插入(仅当有新数据时执行) if (newCoinDocs.length > 0) { await Coin.insertMany(newCoinDocs); }
3. 添加复合索引,加速查询效率
针对name和network的组合查询场景,给Coin集合添加复合唯一索引,既可以大幅提升查询速度,还能从数据库层面避免重复数据:
// 在你的Coin Schema中添加索引 CoinSchema.index({ name: 1, network: 1 }, { unique: true });
可选:用bulkWrite实现更灵活的批量操作
如果后续需要对已存在的记录进行字段更新,可直接使用bulkWrite将"查询+插入/更新"打包为批量操作,进一步简化逻辑:
const operations = data.map(item => ({ updateOne: { filter: { name: item.coin, network: item.network }, update: { $set: { title: item.name, contract: item.contract } }, upsert: true // 不存在则插入,存在则更新 } })); await Coin.bulkWrite(operations);
通过以上优化,数据库交互次数从3000+次降低到2次(查询+插入),处理3000条数据的耗时可压缩到几秒级别。
内容的提问来源于stack exchange,提问作者ali
相关产品推荐
相关产品推荐

