Ответ 1
У вас есть два реальных выбора здесь, в зависимости от того, как вы хотите обрабатывать вещи:
-
Используйте upsert функциональность MongoDB, чтобы существенно "искать", если данные ключа существуют. Если нет, то вы передаете только данные
$setOnInsert
, и это ничего не трогает. -
Используйте операции "UnOrdered" в Bulk. Вся серия обновлений будет продолжена, даже если будет возвращена ошибка, но отчет об ошибках будет таким, и все, что не является ошибкой, будет выполнено.
Весь пример:
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();
}
);
Обратите внимание, что "измененное действие" в текущих драйверах заключается в том, что ответ на результат .execute()
будет возвращать объект ошибки, который должен быть выброшен, где предыдущие выпуски не делали этого с "Un-ordered" операций.
Это делает необходимым, чтобы ваш код никогда не полагался на возвращаемый err
, и вы должны вставлять обратно возвращенный result
для полной классификации ошибок.
Тем не менее, когда неупорядоченный, партия продолжается до конца, независимо от количества ошибок. Вещи, которые не являются ошибкой, будут выполняться как обычно.
Это действительно сводится к тому, что "важна последовательность". Если это так, то вам нужны операции "Заказ", и вы можете избежать дублирования ключей, используя "upserts". В противном случае используйте "неупорядоченные", но имейте в виду, что возвращается ошибка и что они на самом деле означают.
Кроме того, при использовании .collection
, чтобы получить базовый объект коллекции из базового драйвера, чтобы активировать операции "Массовые", всегда убедитесь, что сначала был вызван метод "some" mongoose.
Без этого нет гарантированного подключения к базе данных с помощью собственных методов драйвера, так как она обрабатывается для методов mongoose, поэтому операция не будет выполнена из-за отсутствия соединения.
Альтернативой "стрельбе" методу mongoose во-первых, является объединение вашей логики приложения в прослушиватель событий для соединения:
mongoose.connection.on("open",function(err) {
// app logic in here
})