在DB写入之前,Mongoose调用save回调?

时间:2015-03-08 12:53:24

标签: mysql node.js mongodb csv callback

我在节点上使用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});
            });
        });
    });
}
});

1 个答案:

答案 0 :(得分:3)

你可能在那里遇到了竞争条件,这似乎就是这种情况,因为你说你的脚本第二次运行。

由于async.each并行运行,如果重复的用户名在CSV文件中彼此相邻,则可能会在第一个findOne之前进行两次save次调用

我建议您使用唯一索引强制数据库的唯一性。它也会更具性能(每个用户只能访问一次数据库),而您只需要处理唯一约束错误。