猫鼬在数据库写入之前调用保存回调?

Mongoose calling save callback before DB write?

我正在使用 mongoose with node,我有一些功能允许用户上传 CSV 数据,然后将数据放入 mongo。

我正在尝试防止上传重复的用户名。为了缓解这种情况,我调用 findOne 并在将条目保存到数据库之前查找用户名,如果找到用户名,它应该调用异步的 callback() 并进入下一次迭代。

我有一个保存回调,我希望它只在数据在数据库中时被调用,在这个回调中我调用 callback()

从我的控制台日志中,每个重复的 findOne 都显示为空,但数据实际上正在写入数据库(如果我尝试在 csv 中上传更多重复项,一切都会按预期进行)。

这几乎就像是在数据库写入实际发生之前调用了保存回调,所以下一次调用没有找到重复项,我对 mongo 如何写入数据库有一些根本性的误解吗还是我忽略了一些明显的东西...

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});
            });
        });
    });
}
});

你可能 运行 进入了竞争状态,这似乎是因为你说你的脚本在第二个 运行 上工作 运行。

因为 async.each 运行 是并行的,如果重复的用户名在 CSV 文件中彼此相邻的行中,则可能会在 findOne 之前进行两次调用首先 save 是。

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