我在节点上使用mongoose,我有一些功能允许用户上传CSV,然后将数据放入mongo。
我正在尝试阻止上传重复的用户名。为了缓解这种情况,我调用了findOne并在将条目保存到数据库之前查找用户名,如果它找到了应该调用async' s callback()
的用户名并转到下一次迭代。
我有一个保存回调,我希望只在数据在数据库中时调用,在这个回调中我调用callback()
。
从我的控制台日志中,每个重复的findOne都显示为null,但实际上数据被写入数据库(如果我尝试在csv中上传更多重复项,之后一切都按预期工作)。
几乎就好像在db写入实际发生之前调用了save回调,所以下一个调用没有找到重复,我是否对mongo如何写入db或am am有一些根本的误解我忽略了一些明显的东西......
admin.post('/upload', function(req, res) {
if(req.files.file) {
var file = req.files.file;
fs.readFile(file.path, 'utf8', function(err, data) {
if(err) return res.json({error: err});
csv.parse(data, function(err, parsed) {
// remove header
if(!parsed) {
return;
}
parsed.splice(0, 1);
var headers = ['auth', 'sid', 'fl', 'dd'];
async.each(parsed, function(row, callback) {
var seed = {};
for(var i = 0; i < 4; i++) {
if(row[i] && row[i].trim() !== '') {
seed[headers[i]] = row[i].trim();
}
}
if(seed.user && seed.password) {
User.findOne({username: seed.user}, function(err, result) {
if(err) {
console.log(err);
return res.json({error: err});
}
console.log(result);
if(!result) {
console.log('creating user');
var user = new User({
username: seed.user,
password: User.generateHash(seed.password),
});
user.save(function(err) {
if(err){
return res.json({error: err});
}
console.log('SAVED CALLING CB');
callback();
});
} else {
callback();
}
});
} else {
callback();
}
}, function() {
return res.json({success: true});
});
});
});
}
});
答案 0 :(得分:3)
你可能在那里遇到了竞争条件,这似乎就是这种情况,因为你说你的脚本第二次运行。
由于async.each
并行运行,如果重复的用户名在CSV文件中彼此相邻,则可能会在第一个findOne
之前进行两次save
次调用
我建议您使用唯一索引强制数据库的唯一性。它也会更具性能(每个用户只能访问一次数据库),而您只需要处理唯一约束错误。