我正在使用Sequelize将数据从CSV文件导入Nodejs系统,但在尝试检查以前是否插入过前一行时遇到问题。
这是我正在使用的代码
exports.insertEmployee = function (employee) {
return new Promise((fulfill, reject) => {
models.Employee.create(employee)
.then(employee => fulfill(employee.dataValues))
.catch(reject);
});
};
exports.importEmployee = function (employee) {
return new Promise((fulfill, reject) => {
models.Employee.findOne({where: {customID: employee.customID}, raw: true}).then(emp => {
if(emp) {
fulfill(emp);
}
else {
exports.insertEmployee(employee).then(fulfill);
}
});
});
};
函数importEmployee的调用次数与csv中的行数一样多,如下所示
lines.forEach(line => {
let emp = line.employee;
importEmployee(emp).then(employee => {console.dir(employee)});
});
我遇到的问题是,当我检查具有相同customID的用户是否已经被插入时,数据库还没有提交插入,因此它总是返回false,并且我将有具有相同customID的重复雇员
我该怎么解决这个问题呢?我尝试使用事务,但可能我做错了,因为它不会有帮助。
谢谢!
发布于 2017-03-08 19:43:55
它不起作用,因为在forEach
中,您想要执行一系列异步操作。通过这种方式,所有记录都将被插入,因为执行检查和插入的操作是并发运行的。为了避免这种情况,您可以使用Bluebird模块中的mapSeries()
Promise函数。它内置在sequelize中,因此不需要安装额外的软件包。
此外,您可以通过名为findOrCreate()
的单个操作执行检查和插入,该操作返回一个实例和布尔值,用于定义此实例是创建的还是简单地作为现有实例返回。
当您将这两个功能组合在一起时,您的操作将变得非常简单和直接
// here is the function performing findOrCreate
exports.createEmployee = function(employee) {
return models.Employee.findOrCreate({
where: { customID: employee.customID },
defaults: employee
});
};
更重要的是,您不必像在insertEmployee
和importEmployee
中那样创建嵌套的Promise。大多数sequelize函数已经返回了promises,所以您可以简单地返回函数调用本身。
现在您可以遍历lines
并调用createEmployee
方法。
models.sequelize.Promise.mapSeries(lines, (employee) => {
return createEmployee(employee);
}).then(result => {
console.log(result);
// example output: [ [ Instance, true ], [ Instance, true ], [ Instance, false ] ]
});
布尔值true
表示实例是创建的,而false
表示实例是从表中返回的,因为这样的记录已经存在。
https://stackoverflow.com/questions/42668508
复制相似问题