Masz dwie prawdziwe możliwości wyboru w zależności od tego, jak chcesz sobie z tym poradzić:
-
Użyj upsert funkcjonalność MongoDB, aby zasadniczo „wyszukać”, jeśli istnieją kluczowe dane. Jeśli nie, przekazujesz dane tylko do
$setOnInsert
i to nie dotknie niczego innego. -
Użyj operacji „Nieuporządkowanych” w trybie zbiorczym. Cała partia aktualizacji będzie kontynuowana, nawet jeśli zostanie zwrócony błąd, ale raporty o błędach są właśnie takie i wszystko, co nie jest błędem, zostanie popełnione.
Cały przykład:
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();
}
);
Zauważ, że "zmieniona akcja" w obecnych sterownikach polega na tym, że odpowiedź wynikowa na .execute()
będzie zwraca obiekt błędu, który ma zostać wyrzucony, w przypadku gdy poprzednie wydania nie robiły tego za pomocą operacji „Nieuporządkowanych”.
To sprawia, że konieczne jest, aby Twój kod nigdy nie opierał się na err
zwrócona sama i powinieneś wprowadzać zwrócony result
zamiast tego dla pełnej klasyfikacji błędów.
Niemniej jednak bez zamówienia partia trwa do końca, bez względu na liczbę błędów. Rzeczy, które nie są błędem, zostaną popełnione normalnie.
To naprawdę sprowadza się do „czy kolejność jest ważna”. Jeśli tak, potrzebujesz operacji "Uporządkowanych" i możesz uniknąć zduplikowanych kluczy tylko za pomocą "upserts". W przeciwnym razie użyj „nieuporządkowanego”, ale pamiętaj o zwracanych błędach i o tym, co one właściwie oznaczają.
Również przy użyciu .collection
aby pobrać bazowy obiekt kolekcji ze sterownika podstawowego, aby włączyć operacje "Bulk", zawsze upewnij się, że jako pierwsza zawsze była wywoływana "jakaś" metoda mangusty.
Bez tego nie ma gwarantowanego połączenia z bazą danych za pomocą natywnych metod sterownika, ponieważ jest to obsługiwane w przypadku metod mangusty, więc operacja zakończy się niepowodzeniem z powodu braku połączenia.
Alternatywą dla "odpalenia" metody mangusty jest umieszczenie logiki aplikacji w detektorze zdarzeń dla połączenia:
mongoose.connection.on("open",function(err) {
// app logic in here
})