逐行读取文件,解析它们并将它们插入到节点js中的mongo中

时间:2015-07-15 04:58:05

标签: javascript node.js mongodb

我有一个标签分隔的文件。它有数千个数据。如何使用nodeJs逐行读取文件,解析它们并创建一个对象并将它们插入mongo DB中。

我只是学习节点和mongo。我来自不同的背景。那么怎么做呢。

最后,Mongo DB必须填充适当的数据。 我在网上搜索但我找不到完整的解决方案。

感谢。

3 个答案:

答案 0 :(得分:2)

我遇到了the answer by Juvenik的问题。我的问题是readline完成时不会填充数据库。这些行是同步读取的,但DB插入是异步的。

相反,我找到了一个更简单的line-reader包解决方案。它会在继续之前读取行并等待回调。

var MongoClient = require('mongodb').MongoClient

var dbName = 'yourDbName'
var url = 'mongodb://localhost:27017/' + dbName
var collectionName = 'yourCollectionName'
var filename = 'yourFileName.txt'

var printLine = 1000

MongoClient.connect(url, function(err, db) {
    if (err) {
        console.error('Problem connecting to database')
    } else {
        console.log('Connected correctly to server.')

        var lineReader = require('line-reader')

        var collection = db.collection(collectionName)
        var lineNum = -1
        var headers = []

        lineReader.eachLine(filename, function(line, last, cb) {
            lineNum++
            try {
                var split = line.split('\t')
                var object = {}

                if (lineNum > 0) {
                    for (var i = 0; i < split.length; i += 1) {
                        object[headers[i]] = split[i]
                    }

                    collection.insert(object, function (insertErr, insertObj) {
                        if (insertErr) console.error(insertErr)
                        if (lineNum % printLine === 0) console.log('Line ' + lineNum)
                        if (last) {
                            console.log('Done with ' + filename + ' (' + lineNum + ' records)')
                            process.exit(0)
                        } else {
                            cb()
                        }
                    })

                } else {
                    headers = line.split('\t')
                    cb()
                }

            } catch (lineError) {
                console.error(lineError)
            }
        })
    }
})

答案 1 :(得分:0)

我遇到过类似的问题。这种方法对我有用。 看看,它可能会有所帮助。

var mongoDb         = require('mongodb');
var mongoClient     = mongoDb.MongoClient;
var dbname          = 'YOUR_DB_NAME';
var collectionName  = 'YOUR_COLLECTION_NAME';
var url             = 'mongodb://localhost:27017/'+dbname;
var filename        = 'FIle_Name.txt';
console.log('***************Process started');

mongoClient.connect(url,function(err,db){
    if(err){
        console.log('error on connection '+err);
    }
    else{
        console.log('***************Successfully connected to mongodb');
        var collection  = db.collection(collectionName);
        var fs          = require('fs');
        var readline    = require('readline');
        var stream      = require('stream');
        var instream    = fs.createReadStream(filename);
        var outstream   = new stream;
        var rl          = readline.createInterface(instream,outstream);

        console.log('***************Parsing, please wait ...');

        rl.on('line',function(line){
            try{
                var arr         = line.split('\t');
                var object   = {};
                //Parse them here
                //Example
                object['name'] = arr[0]; //Just an example
                var res = collection.insert(object);
            }
            catch (err){
                console.log(err);
            }
        });

        rl.on('close',function(){
            db.close();
            console.log('***************completed');
        });
    }
});

我也是学习者。如果有人能做得更好,那就更好了。

答案 2 :(得分:0)

这是frank-0's answer

的更高性能(插入批量对象)和更新版本(使用异步和最新的mongo驱动程序)
const lineReader = require('line-reader');

async function readFileAndInsertInMongo(file) {
    let total = 0;

    return new Promise((resolve, reject) => {
        let buffer = [];
        lineReader.eachLine(file, (line, last, cb) => {
            // prepare your object based on the line content
            let insertObject = {'some_content': 'some_value'};

            if (total % 10000 === 0 || last) {
                collection.insertMany(buffer, function(err, res){
                    if (last) {
                        if (err) {
                           reject(err);
                        } else {
                           resolve(res);
                        }
                    } else {
                        buffer = [];
                        return cb();
                    }
                });
            } else {
                buffer.push(insertObject);
                return cb();
            }
        });
    });
}

这确实是我发现解析大文件并将其插入数据库而不会爆炸Node内存的最佳解决方案。希望这可以帮助;)