3 Stimmen

Mongodb-Inserts werden nicht erfolgreich abgeschlossen (mit node.js)

Ich habe ein node.js-Skript, das eine XML-Datei lädt. Es durchläuft jedes Element im Mongo-Array und sagt dass sie alle korrekt eingefügt werden, aber wenn das Skript eine Überprüfung der db.collection.count(); sagt mir, dass viel weniger Datensätze in die Datenbank eingefügt wurden als erwartet.

Wie kann ich Mongo und Node.js dazu bringen, gut mit Inserts zu spielen?

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

Wie gewünscht, finden Sie den Code oben. Die Datei wird lokal gelesen (obwohl es früher eine HTTP-Anfrage war, aber jetzt ist es eine 25-Meg-Datei, viele RSS-Datensätze)

Ich habe gerade die Datei mit etwa 10.000 Datensätzen ausgeführt, und die Zählung der Elemente in der MongoDB nach Ausführung des Skripts ergibt etwa 800 Elemente.

Wie in der Antwort angegeben, habe ich den Einfügecode ersetzt:

mit:

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

7voto

Brendan W. McAdams Punkte 9246

Standardmäßig wird bei MongoDB-Schreibvorgängen nicht auf einen Fehler geprüft.

Sie müssen Folgendes einstellen safe:true in den Optionen für Ihre Einfügung, wie in der Dokumentation für node-mongodb-native beschrieben:

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

Andernfalls wird Ihr Callback bei Fehlern nicht aufgerufen und Ihr Client erfährt nichts davon.

Wahrscheinlich möchten Sie auch Upserts und Updates betrachten, da es unglaublich ineffizient ist, find & insert if null in einer Schleife durchzuführen.

Stattdessen aktualisiert upsert, wenn das entsprechende Dokument existiert, andernfalls wird ein neues eingefügt. Eine Erklärung, wie man dies in Node macht, findet sich in der Dokumentation des Treibers.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X