Sie haben hier zwei wirkliche Möglichkeiten, je nachdem, wie Sie die Dinge handhaben möchten:
-
Verwenden Sie upsert Funktionalität von MongoDB, um im Wesentlichen nachzuschlagen, ob die Schlüsseldaten vorhanden sind. Wenn nicht, geben Sie die Daten nur an
$setOnInsert
und das wird nichts anderes berühren. -
Verwenden Sie "Ungeordnete" Operationen in Bulk. Der gesamte Update-Stapel wird auch dann fortgesetzt, wenn ein Fehler zurückgegeben wird, aber die Fehlerberichte sind genau das, und alles, was kein Fehler ist, wird übernommen.
Ganzes Beispiel:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
var testSchema = new Schema({
"_id": Number,
"name": String
},{ "_id": false });
var Test = mongoose.model('Test',testSchema,'test');
mongoose.connect('mongodb://localhost/test');
var data = [
{ "_id": 1, "name": "One" },
{ "_id": 1, "name": "Another" },
{ "_id": 2, "name": "Two" }
];
async.series(
[
// Start fresh
function(callback) {
Test.remove({},callback);
},
// Ordered will fail on error. Upserts never fail!
function(callback) {
var bulk = Test.collection.initializeOrderedBulkOp();
data.forEach(function(item) {
bulk.find({ "_id": item._id }).upsert().updateOne({
"$setOnInsert": { "name": item.name }
});
});
bulk.execute(callback);
},
// All as expected
function(callback) {
Test.find().exec(function(err,docs) {
console.log(docs)
callback(err);
});
},
// Start again
function(callback) {
Test.remove({},callback);
},
// Unordered will just continue on error and record an error
function(callback) {
var bulk = Test.collection.initializeUnorderedBulkOp();
data.forEach(function(item) {
bulk.insert(item);
});
bulk.execute(function(err,result) {
callback(); // so what! Could not care about errors
});
},
// Still processed the whole batch
function(callback) {
Test.find().exec(function(err,docs) {
console.log(docs)
callback(err);
});
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
Beachten Sie, dass die „geänderte Aktion“ in aktuellen Treibern darin besteht, dass das Ergebnis auf .execute()
antwortet wird gibt ein zu werfendes Fehlerobjekt zurück, wo frühere Releases dies bei "ungeordneten" Operationen nicht getan haben.
Daher ist es unerlässlich, dass Ihr Code niemals auf err
angewiesen ist allein zurückgegeben, und Sie sollten das zurückgegebene result
eingeben stattdessen für die vollständige Klassifizierung von Fehlern.
Nichtsdestotrotz läuft der Batch im ungeordneten Zustand bis zum Ende weiter, egal wie viele Fehler auftreten. Dinge, die kein Fehler sind, werden ganz normal übergeben.
Dies läuft wirklich darauf hinaus, "ist die Reihenfolge wichtig". Wenn ja, dann benötigen Sie "Ordered"-Operationen und können doppelte Schlüssel nur durch "Upserts" vermeiden. Verwenden Sie andernfalls "unordered", aber beachten Sie die Fehlermeldungen und was sie tatsächlich bedeuten.
Auch bei Verwendung von .collection
Um das zugrunde liegende Sammlungsobjekt vom Basistreiber zu erhalten, um "Massen"-Operationen zu ermöglichen, stellen Sie immer sicher, dass eine "irgendeine" Mungo-Methode immer zuerst aufgerufen wurde.
Ohne dies gibt es mit den Methoden des nativen Treibers keine garantierte Verbindung zur Datenbank, wie es für die Mongoose-Methoden gehandhabt wird, sodass der Vorgang aufgrund fehlender Verbindung fehlschlägt.
Die Alternative zum „Abfeuern“ einer Mungo-Methode besteht darin, Ihre App-Logik in einen Ereignis-Listener für die Verbindung einzuschließen:
mongoose.connection.on("open",function(err) {
// app logic in here
})