[英]How to use sequelize findorcreate in bulk import?
我正在尝试在 CSV 导入中使用findOrCreate
函数来防止使用相同的电子邮件地址创建多个用户,但它不起作用。
我将 CSV 文件中的所有行导入内存:
importableCsvRows.forEach(row => importData(row))
然后我遍历每一行来导入一个用户:
function importData (row) {
const name = row[0]
const email = row[1]
addUser(name, email)
}
在 addUser 函数中,我使用 findOrCreate:
function addUser (name, email) {
return new Promise(function (resolve, reject) {
const user = models.users.findOrCreate({
where: {email: email},
defaults: { email: email, name: name }
})
.then(u => {
return resolve(u)
})
.catch(err => {
console.log('ERROR', err)
return reject(err)
})
})
}
问题是多个事务开始了,因为 findOrCreate 是异步的,所以在第一行完成处理之前,下一行开始。
在您的forEach
您需要等到 db 事务完成后再开始导入下一个用户。
最简单的方法是等待importData
函数:
async function importData (row) {
const name = row[0]
const email = row[1]
try {
await addUser(name, email)
} catch(err) {
//console.log?
}
}
此外,在addUser
:无需返回您自己的 Promise。 只需返回承诺findOrCreate
返回:
function addUser (name, email) {
return models.users.findOrCreate({
where: {email: email},
defaults: { email: email, name: name }
})
})
}
由于findOrCreate
没有本地批量替代findOrCreate
,我们必须手动完成(正如您已经尝试过的那样)。
Promise.all
+ map
在这里很有帮助。 Promise.all
并行运行所有请求,并充当屏障,等待所有承诺完成。
这是一个简单的工作代码示例:
async function addUserRows(userRow) {
return await Promise.all(
rows.map(addUserRow)
);
}
async function addUserRow(row) {
const [name, email] = row;
return addUser(name, email)
}
async function addUser (name, email) {
return models.users.findOrCreate({
where: {email},
defaults: { email, name }
});
}
如果您改用 Bluebird 的Promise.map ,事情会变得简单一些,您甚至可以限制正在进行的承诺的最大并发数量,如果您有很多行,这绝对是可取的。
但是,更高级的方法是使用两个顺序查询:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.