2011-05-22 48 views
4

我有一個加載XML文件的node.js腳本。它循環遍歷Mongo數組中的每個元素,並且它們都被正確插入,但是當腳本完成db.collection.count();檢查時,告訴我數據庫中插入的記錄少於預期的數量。Mongodb插入未成功完成(使用node.js)

我該如何讓mongo和node.js和inserts一起玩呢?

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請求,但現在是一個25兆文件,大量的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); 
     } 
}); 
+0

你似乎已經錯過了你的描述有什麼... – jcolebrand 2011-05-22 02:42:03

+0

你能更多詳細信息添加到這個問題,也許張貼一些代碼? – 2011-05-22 03:01:06

回答

8

默認情況下,MongoDB的寫入不檢查一個錯誤。

你需要設置的選項來您的插入safe:true,作爲文檔中解釋節點MongoDB的本地:

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 
    } 
}); 

否則你的回調將不會被調用的錯誤和您的客戶端將不瞭解他們。

您可能還想查看upserts和更新,因爲如果在循環中爲null,那麼發現&插入的效率非常低。

相反,如果匹配的文檔存在,upsert會更新,否則會插入一個新的。有關如何在Node中執行此操作的解釋,請參閱驅動程序的文檔。

+0

更新工作* *很多*更好。第一次運行10K/10K,即將嘗試30K文件。 – 2011-05-22 04:16:57

+1

現在運行了大約10分鐘,但到目前爲止,它看起來像100%的記錄進入。非常感謝。 upsert代碼的方式也比較乾淨 – 2011-05-22 04:32:02

+0

如果使用「mongodb:// localhost /?safe = true」連接字符串,則MongoDb會檢查每個寫入操作。你可以閱讀http://www.mongodb.org/display/DOCS/Connections – Erhan 2011-12-28 13:04:30