策略和技术手段
- 文件读取优化:
- 流处理:使用 Node.js 的
fs.createReadStream
以流的方式读取文件,避免一次性将整个文件读入内存,减少内存占用。
- 队列处理:为避免过多并发导致性能问题,可以使用队列来控制文件读取的并发数量,例如
async
库的 queue
。
- 数据库插入优化:
- 批量插入:使用 MongoDB 的
insertMany
方法代替单个插入,减少数据库交互次数。
- 连接池:使用
mongoose
或原生 MongoDB 驱动时,合理配置连接池,复用数据库连接,减少连接建立和销毁的开销。
核心代码示例
const fs = require('fs');
const path = require('path');
const { MongoClient } = require('mongodb');
const async = require('async');
// 数据库连接配置
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
const dbName = "yourDatabaseName";
const collectionName = "documents";
// 读取文件目录
const directoryPath = path.join(__dirname, 'yourFilesDirectory');
async function main() {
try {
// 连接数据库
await client.connect();
console.log('Connected to MongoDB');
const db = client.db(dbName);
const collection = db.collection(collectionName);
// 读取目录下所有文件
const files = fs.readdirSync(directoryPath);
// 使用队列控制并发读取文件
const q = async.queue(async (file, callback) => {
const filePath = path.join(directoryPath, file);
const data = await new Promise((resolve, reject) => {
let fileData = '';
const readStream = fs.createReadStream(filePath, { encoding: 'utf8' });
readStream.on('data', (chunk) => {
fileData += chunk;
});
readStream.on('end', () => {
resolve(fileData);
});
readStream.on('error', (err) => {
reject(err);
});
});
const jsonData = JSON.parse(data);
callback(null, jsonData);
}, 5); // 并发数设为5
const allData = [];
q.drain(() => {
// 批量插入数据到 MongoDB
collection.insertMany(allData)
.then(() => {
console.log('Data inserted successfully');
})
.catch((err) => {
console.error('Error inserting data:', err);
})
.finally(() => {
client.close();
});
});
files.forEach((file) => {
q.push(file, (err, result) => {
if (!err) {
allData.push(result);
}
});
});
} catch (e) {
console.error(e);
}
}
main();