【问题标题】:How to use sequelize findorcreate in bulk import?如何在批量导入中使用 sequelize findorcreate?
【发布时间】:2018-06-20 07:28:03
【问题描述】:

我正在尝试在 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 是异步的,所以在第一行完成处理之前,下一行开始。

【问题讨论】:

标签: javascript node.js asynchronous sequelize.js


【解决方案1】:

在您的forEach 中,您需要等到数据库事务完成才能开始导入下一个用户。

最简单的方法是awaitimportData函数:

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

【讨论】:

  • 这不起作用,forEach 不会等待迭代之间的承诺
【解决方案2】:

由于findOrCreate 没有本地批量替代品,我们必须手动完成(正如您已经尝试过的那样)。

Promise.all + map 在这里会有所帮助。 Promise.all 并行运行所有请求,并充当 Barrier 等待所有承诺都得到满足。

这是一个简单的工作代码示例:

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,事情会变得简单一些,您甚至可以限制运行中 promise 的最大并发数量,如果您有很多行,这绝对是可取的。

但是,更高级的方法是使用两个顺序查询:

  1. 第一个查询获取所有缺失的条目。
  2. 第二个查询写入所有缺失的条目(使用bulkCreate
  3. 如果您的行太多,请将大集合分成较小的批次并重复,直到所有批次都发送出去。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    • 2015-03-31
    • 2015-06-10
    • 2017-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多