以下代码正确遍历文件系统.如您所见,它会读取目录中的每个项目,如果该项目是目录,则会读取其中的每个项目.对于不是目录的每个项目,它在发送保存到函数的变量之前对其执行一些操作.
function traverseFS (path){ var files = fs.readdirSync(path); for (var i in files){ var currentFile = path + '/' + files[i]; var stats = fs.statSync(currentFile); if (stats.isFile()) runOnFile(currentFile); else traverseFS(currentFile); } } traverseFS("D:/njs/nodetest1/imports/source1/")
接下来,我对代码运行一些操作(见下文).这将读取文件,将其解析为JSON对象,将该对象的两个属性读入变量,在变量“entry”中创建一个对象,并将该变量传递给另一个函数.
function runOnFile(currentFile){ var fileText = fs.readFileSync(currentFile,'utf8'); var generatedJSON = JSON.parse(fileText); var recordID = generatedJSON.recordID; var recordText = generatedJSON.recordTexts; var entry = {recordID:recordID,recordText:recordText}; insertRecord(entry); }
然后应该使用最终函数将数据插入mongoDB.我认为这是出问题的地方.
function insertRecord(entry){ var MongoClient = mongodb.MongoClient; var MongoURL = 'mongodb://localhost:27017/my_database_name'; MongoClient.connect(MongoURL,function (err,db) { var collection = db.collection('users'); collection.insert([entry],result) { db.close(); }); }); }
我希望这会运行文件结构,将JSON文件读入对象,然后将这些对象插入到我的mongoDB中.相反,它将第一个文件读入数据库,然后停止/挂起.
笔记:
>我不想使用mongoimport,因为我不想将这些文件中的所有数据插入到我的MongoDB数据库中.然而,我并不依赖于这种方法的任何方面.如果存在其他解决方案,我愿意接受.
>这很好地连接到数据库.对于目录中的每个项目,这将成功创建一个“条目”对象并将其传递给insertRecord函数.换句话说,问题必须出现在insertRecord部分.但显然这可能是由于此过程中的某些原因造成的.
>如果我添加错误处理,则不会产生错误.我已经将错误处理从这篇文章中删除了,因为它使代码片段的可读性变得混乱.
解决方法
mongodb
2.2 (current latest) documentation,不推荐使用insert
DEPRECATED
Use insertOne,insertMany or bulkWrite
所以简短的回答可能是将collection.insert([entry],…)改为collection.insertOne(entry,…),你就完成了.
然后,对于长时间的回答,您说“大约有一百万个json文件”,这通常需要一个完全异步的方法,并且开销最小.
示例代码中存在两个(潜在的)瓶颈:
> fs.readFileSync,这是一个阻塞操作
>连接,插入记录和关闭数据库连接
两者都执行“大约一百万次”.当然,导入通常不会一次又一次地进行,并且(希望)不会在需要其性能用于其他重要任务的机器上进行.尽管如此,示例代码仍然可以更加健壮.
glob('imports/**/*.json',function(error,files) {...})
这样可以轻松地以异步方式为您提供完整的文件列表.
保持与样本中的步骤大致相同,我建议如下:
var glob = require('glob'),mongodb = require('mongodb'),fs = require('fs'),MongoClient = mongodb.MongoClient,mongoDSN = 'mongodb://localhost:27017/my_database_name',collection; // moved this to the "global" scope so we can do it only once function insertRecord(json,done) { var recordID = json.recordID || null,recordText = json.recordText || null; // the question implies some kind of validation/sanitation/preparation.. if (recordID && recordText) { // NOTE: insert was changed to insertOne return collection.insertOne({recordID: recordID,recordText: recordText},done); } done('No recordID and/or recordText'); } function runOnFile(file,done) { // moved to be async fs.readFile(file,data) { if (error) { return done(error); } var json = JSON.parse(data); if (!json) { return done('Unable to parse JSON: ' + file); } insertRecord(json,done); }); } function processFiles(files,done) { var next = files.length ? files.shift() : null; if (next) { return runOnFile(next,function(error) { if (error) { console.error(error); // you may or may not want to stop here by throwing an Error } processFiles(files,done); }); } done(); } MongoClient.connect(mongoDSN,db) { if (error) { throw new Error(error); } collection = db.collection('users'); glob('imports/**/*.json',files) { if (error) { throw new Error(error); } processFiles(files,function() { console.log('all done'); db.close(); }); }); });
注意:您可以使用insertMany收集多个“条目”记录以利用多个插入的性能增益,但我感觉插入的记录比描述的更复杂,如果处理不当,可能会给出一些内存问题.