Du har två riktiga val här beroende på hur du vill hantera saker och ting:
-
Använd upsert funktionalitet hos MongoDB för att i huvudsak "söka upp" om nyckeldata finns. Om inte så skickar du bara in data till
$setOnInsert
och det kommer inte att röra något annat. -
Använd "Obeställda" operationer i bulk. Hela batchen av uppdateringar kommer att fortsätta även om ett fel returneras, men felrapporten(erna) är just det, och allt som inte är ett fel kommer att begås.
Helt exempel:
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();
}
);
Observera att den "ändrade åtgärden" i nuvarande drivrutiner är att resultatsvaret på .execute()
kommer returnera ett felobjekt som ska kastas, där tidigare versioner inte gjorde det med "Obeställda" operationer.
Detta gör det absolut nödvändigt att din kod aldrig förlitar sig på err
returneras ensam, och du bör inspetsera det returnerade result
istället för fullständig klassificering av fel.
Icke desto mindre, när den inte är beställd fortsätter partiet till slutet, oavsett hur många fel som uppstår. Saker som inte är ett fel kommer att begås som vanligt.
Detta kommer verkligen ner på "är sekvens viktig". Om så är fallet behöver du "Beställda" operationer och du kan bara undvika dubbletter av nycklar genom att använda "upserts". Använd annars "oordnat", men var uppmärksam på felreturerna och vad de faktiskt betyder.
Även när du använder .collection
för att få det underliggande samlingsobjektet från basdrivrutinen för att aktivera "Bulk"-operationer, var sedan alltid säker på att antingen "någon" mongoose-metod alltid har anropats först.
Utan det finns det ingen garanterad anslutning till databasen med de inbyggda drivrutinsmetoderna eftersom den hanteras för mongoosemetoderna, så operationen kommer att misslyckas på grund av ingen anslutning.
Alternativet till att först "avfyra" en mangustmetod är att linda in din applogik i en händelseavlyssnare för anslutningen:
mongoose.connection.on("open",function(err) {
// app logic in here
})