【发布时间】:2020-04-19 04:03:56
【问题描述】:
我通过以下方式简化我的 Mongoose 模型:假设我有一个模型 Bank,带有子文档 Users,每个模型都有一个 Transfers 数组
BankSchema = {
bank_name : {type:String},
users : [
{
user_name : {type:String},
transfers : [
{
amount : {type:Number},
date : {type:Date}
}
]
}
]
}
BankSchema 有一个添加转账的方法,可以找到正确的用户并将转账添加给他
BankSchema.methods.addTransfer(user_name, new_transfer)
{
var bank = this;
for(let u in bank.users)
{
if(bank.users[u].name == user_name)
{
bank.users[u].transfers.push(new_transfer);
break;
}
}
return bank.save(); // promise
}
现在,假设我有一个不同银行转账的 csv 文件要导入,所以我这样做了
/*
csv will give rows like {bank_id:'', user_name:'', transition:{} }
*/
for(let i in csv)
{
var row = csv[i];
Bank.findById(row.bank_id)
.then(function(bank)
{
// addTransfer also save() the document
bank.addTransfer(row.user_name, row.transition);
})
.catch(function(err)
{
console.error(err);
// this gives: VersionError: No matching document found for...
})
}
在循环中,每次找到银行时,修改并保存。所以我不是在同一版本中并行修改多次,而是每次都重新找一遍。我认为这足以避免 Mongo VersionError,但可能我错了。
不能同时“添加子文档”吗?
"mongoose": "^5.4.20",
$npm --version 6.4.1
======= 更新 1 =======
在与 Oleg 讨论后(见他的回答),我想处理这个错误,然后再试一次。除了大量导入之外,在运行时可能会发生不同用户同时添加传输的情况。但它们应该是非常罕见的情况,所以“再试一次”可能是一个解决方案?比如:
function main()
{
for(let i in csv)
{
var row = csv[I];
// in parallel, not blocking
addTransferToBank(row.bank_id, row.user_name, row.transition);
}
}
function addTransferToBank(bank_id, user_name, transition)
{
var deferred = Q.defer();
Bank.findById(bank_id)
.then(function(bank)
{
// addTransfer also save() the document
return bank.addTransfer(user_name, transition);
})
.then(function()
{
deferred.resolve(true); // ok, done
})
.catch(function(err)
{
if(err && err.name && err.name == "VersionError")
{
// TRY AGAIN
deferred.resolve(addTransferToBank(bank_id, user_name, transition)); // I could also run it after a timeout
}
else
{ deferred.reject(err); }
})
return deferred.promise;
}
【问题讨论】: