【问题标题】:Mongodb inserts not completing successfully (using node.js)Mongodb 插入未成功完成(使用 node.js)
【发布时间】:2011-08-30 10:49:10
【问题描述】:

我有一个加载 XML 文件的 node.js 脚本。它循环遍历 Mongo 数组中的每个元素,说它们都被正确插入,但是当脚本完成对 db.collection.count(); 的检查时,告诉我插入的记录要少得多数据库数量超出预期。

如何让 mongo 和 node.js 与插入很好地配合?

GrabRss = function() {
var http    = require('http');
var sys     = require('sys');
var xml2js  = require('xml2js');
var fs      = require('fs');

var Db      = require('../lib/mongodb').Db,
    Conn    = require('../lib/mongodb').Connection,
    Server  = require('../lib/mongodb').Server,
    // BSON = require('../lib/mongodb').BSONPure;
    BSON    = require('../lib/mongodb').BSONNative;

var data;
var checked = 0;
var len = 0;

GotResponse = function(res) {
    var ResponseBody = "";
    res.on('data', DoChunk);
    res.on('end', EndResponse);

    function DoChunk(chunk){
        ResponseBody += chunk;
    }
    function EndResponse() {
        //console.log(ResponseBody);
        var parser = new xml2js.Parser();
        parser.addListener('end', GotRSSObject);
        parser.parseString(ResponseBody);
    }
}

GotError = function(e) {
    console.log("Got error: " + e.message);
}

GotRSSObject = function(r){
    items = r.item;
    //console.log(sys.inspect(r));

    var db = new Db('myrssdb', new Server('localhost', 27017, {}), {native_parser:false});
    db.open(function(err, db){
         db.collection('items', function(err, col) {
            len = movies.length;
            for (i in items) {
                SaveItem(items[i], col);
            }
         });
    });
}

SaveItem = function(m, c) {
            /*  REPLACE FROM HERE IN ANSWER  */
    c.find({'id': m.id}, function(err, cursor){
        cursor.nextObject(function(err, doc) { 
            if (doc == null) {
                c.insert(m, function(err, docs) {
                    docs.forEach(function(doc) {
                        console.log('Saved: '+doc.id+' '+doc.keywords);
                    });
                });
            } else {
                console.log('Skipped: '+m.id);
            }
            if (++checked >= len) {
                process.exit(0);
            } 
        });
    });
            /*  REPLACE TO HERE IN ANSWER  */
}
//http.get(options, GotResponse).on('error', GotError);
var x2js = new xml2js.Parser();

fs.readFile('/home/ubuntu/myrss.rss', function(err, data) {
    x2js.parseString(data);
});

x2js.addListener('end', GotRSSObject);

}
GrabRss();

根据要求,代码在上面。本地读取文件(虽然以前是HTTP请求,但现在是25meg文件,RSS记录很多)

我刚刚运行了包含大约 10k 条记录的文件,脚本运行后 mongoDB 中的项目数约为 800 个。

根据答案,我替换了插入代码:

与:

c.update({'id': m.id}, {$set: m}, {upsert: true, safe: true}, function(err){
    if (err) console.warn(err.message);
        else console.log(m.keywords);
        if (++checked >= len) {
            console.log(len);
            //process.exit(0);

            process.exit(0);
        } 
});

【问题讨论】:

  • 您的描述中似乎遗漏了一些内容...
  • 您能否在问题中添加更多细节,并发布一些代码?

标签: mongodb node.js insert data-integrity


【解决方案1】:

默认情况下,MongoDB 写入不会检查错误。

您需要在插入的选项中设置 safe:true,如 node-mongodb-native 的文档中所述:

var collection = new mongodb.Collection(client, 'test_collection');
collection.insert({hello: 'world'}, {safe:true},
                  function(err, objects) {
  if (err) console.warn(err.message);
  if (err && err.message.indexOf('E11000 ') !== -1) {
    // this _id was already inserted in the database
  }
});

否则您的回调将不会因错误而被调用,您的客户也不会知道它们。

您可能还想查看 upsert 和更新,因为在循环中执行 find 和 insert if null 是非常低效的。

相反,如果匹配文档存在,则 upsert 将更新,否则它将插入一个新文档。关于如何在 Node 中执行此操作的说明在驱动程序的文档中。

【讨论】:

  • 更新效果更好很多。 10K/10K第一次跑进去,准备试试30K文件。
  • 现在已经运行了大约 10 分钟,但到目前为止,似乎 100% 的记录都进入了。非常感谢。 upsert 代码也更干净
  • 如果您使用“mongodb://localhost/?safe=true”连接字符串,MongoDb 会检查每次写入。你可以阅读mongodb.org/display/DOCS/Connections
猜你喜欢
  • 1970-01-01
  • 2020-01-02
  • 2016-05-05
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
  • 2014-12-04
  • 1970-01-01
  • 2019-12-22
相关资源
最近更新 更多