sequelize - 删除多行,然后批量插入

时间:2018-06-08 07:25:53

标签: node.js sequelize.js

我需要根据3个字段从表中删除多行。这些字段不是关键列。 POST请求发送所有行。 Sequelize不支持基于列的批量删除。所以我正在运行一个forEach循环来删除,然后想要使用bulkCreate插入。

但" .then()"我创建的自定义函数不存在。任何人都可以提出更好的方法。 谢谢!

create: (req, res) => {
  req.body.rows.forEach((row) => {
    models.AFT_DC_AREA_DAY_AOP.findOne({
        where: { CNTRY_CD: row['CNTRY_CD'], AREA_ORG_LVL_ID: row['AREA_ORG_LVL_ID'], BUS_DT: row['BUS_DT'] },
        individualHooks: true,
        defaults: {
          CNTRY_CD: row['CNTRY_CD'],
          FSCL_YR_NUM: row['FSCL_YR_NUM'],
          FSCL_PER_SID: row['FSCL_PER_SID'],
          FSCL_WK_BEG_DT: row['FSCL_WK_BEG_DT'],
          BUS_DT: row['BUS_DT'],
          AREA_ORG_LVL_ID: row['AREA_ORG_LVL_ID'],
          AREA_AOP_SALES: row['AREA_AOP_SALES']
        }}).then((data, err) => {
            if(err) {
                return res.status(500).json({ error: 'Internal Server Error' });
            }
            if(data) {
                models.AFT_DC_AREA_DAY_AOP.update(
                {
                  CNTRY_CD: row['CNTRY_CD'],
                  FSCL_YR_NUM: row['FSCL_YR_NUM'],
                  FSCL_PER_SID: row['FSCL_PER_SID'],
                  FSCL_WK_BEG_DT: row['FSCL_WK_BEG_DT'],
                  BUS_DT: row['BUS_DT'],
                  AREA_ORG_LVL_ID: row['AREA_ORG_LVL_ID'],
                  AREA_AOP_SALES: row['AREA_AOP_SALES']
                }, {
                    where: {
                        id: data.id
                    }
                }).then((updateData, err) => {
                    if(err) {
                        return res.status(500).json({ error: 'Internal Server Error' });
                    }
                    res.status(200).json(updateData);
                });
            } else {
                models.AFT_DC_AREA_DAY_AOP.create(
                {
                  CNTRY_CD: row['CNTRY_CD'],
                  FSCL_YR_NUM: row['FSCL_YR_NUM'],
                  FSCL_PER_SID: row['FSCL_PER_SID'],
                  FSCL_WK_BEG_DT: row['FSCL_WK_BEG_DT'],
                  BUS_DT: row['BUS_DT'],
                  AREA_ORG_LVL_ID: row['AREA_ORG_LVL_ID'],
                  AREA_AOP_SALES: row['AREA_AOP_SALES']
                }).then((createData, err) => {
                    if(err) {
                        return res.status(500).json({ error: 'Internal Server Error' });
                    }
                    res.status(200).json(createData);
                });
            }

        });
  });

如果记录存在,我想更新记录,如果记录不存在则插入。以下是我的代码:

 create: (req, res) => {
let UpdateOrCreate= function(rows){
    var promises = [];
    rows.forEach((row) => {
       promises.push(insert(row));
    });
    return Promise.all(promises);
}
let insert = function(row){
  return new Promise((resolve,reject)=>{
    var newPromise = models.TABLE.findOne({
        where: { CNTRY_CD: row['CNTRY_CD'], AREA_ORG_LVL_ID: row['AREA_ORG_LVL_ID'], BUS_DT: row['BUS_DT'] },
        individualHooks: true,
        defaults: {
          CNTRY_CD: row['CNTRY_CD'],
          FSCL_YR_NUM: row['FSCL_YR_NUM'],
          FSCL_PER_SID: row['FSCL_PER_SID'],
          FSCL_WK_BEG_DT: row['FSCL_WK_BEG_DT'],
          BUS_DT: row['BUS_DT'],
          AREA_ORG_LVL_ID: row['AREA_ORG_LVL_ID'],
          AREA_AOP_SALES: row['AREA_AOP_SALES']
        }
      }).then((data, err) => {
            if(err) {
              reject('Internal Server Error');
            }
            if(data) {
              models.TABLE.update(
                {
                  CNTRY_CD: row['CNTRY_CD'],
                  FSCL_YR_NUM: row['FSCL_YR_NUM'],
                  FSCL_PER_SID: row['FSCL_PER_SID'],
                  FSCL_WK_BEG_DT: row['FSCL_WK_BEG_DT'],
                  BUS_DT: row['BUS_DT'],
                  AREA_ORG_LVL_ID: row['AREA_ORG_LVL_ID'],
                  AREA_AOP_SALES: row['AREA_AOP_SALES']
                }, {
                    where: {
                      id:data['dataValues']['id']
                    }
                }).then((updateData, err) => {
                    if(err) {
                      reject('Internal Server Error');
                    }
                    resolve(updateData);
                });
            } else {
                models.TABLE.create(
                {
                  CNTRY_CD: row['CNTRY_CD'],
                  FSCL_YR_NUM: row['FSCL_YR_NUM'],
                  FSCL_PER_SID: row['FSCL_PER_SID'],
                  FSCL_WK_BEG_DT: row['FSCL_WK_BEG_DT'],
                  BUS_DT: row['BUS_DT'],
                  AREA_ORG_LVL_ID: row['AREA_ORG_LVL_ID'],
                  AREA_AOP_SALES: row['AREA_AOP_SALES']
                }).then((createData, err) => {
                    if(err) {
                      reject('Internal Server Error');
                    }
                    resolve(createData);
                });
            }

        });
  })
}
UpdateOrCreate(req.body.rows).then(function (result) {
  console.log("%%%%%%%%%%%%%%%%%%%%%%%%");
  console.log(result);
  console.log("%%%%%%%%%%%%%%%%%%%%%%%%");

    res.status(200).json(`${req.body.rows.length} rows successfully inserted!`);
}).catch(function (err) {
    return res.status(500).json({ error: 'Internal Server Error' });
});

}

我收到以下错误"未处理拒绝错误:发送后无法设置标头。"这是有道理的,因为响应已经发送。不确定如何对所有记录执行操作,然后发送响应。

我更新了代码以返回每行的承诺,收集承诺并返回它们。这段代码工作正常。

suggest

}

但是,我想确保错误得到妥善处理。我在插入过程中断开了数据库。它会为循环中的每个失败记录抛出以下错误:

  

未处理的拒绝TimeoutError:ResourceRequest超时   未处理的拒绝SequelizeHostNotFoundError:无法连接到主机

不是决心,拒绝应该处理此错误。我在这里错过了什么吗?

2 个答案:

答案 0 :(得分:0)

要使用Sequelize删除记录,您使用的是正确的。它会根据您提供的条件删除记录,如下所示。 Sequelize documentation

Model.destroy({
    where: {
        // criteria
    }
})

所以你使用for循环迭代列表并删除它。但是您的自定义函数(deleteRows)不支持.then,因此您遇到了删除记录的问题。

我建议你使用promise来使你的功能如下所示。它将返回解决或拒绝。 Promise Documentation

deleteRows: function(rows){
  return new Promise(function(resolve, reject){
    rows.forEach((row) => {
      models.TABLE.destroy({ where: {CNTRY_CD: row['CNTRY_CD'], AREA_ID: row['AREA_ID'], BUS_DT: row['BUS_DT']}})
      .then((region, err) => {
        if(err) {
          console.log("I am here");
          reject('Internal Server Error');
        }

        resolve(region);
      });
    });
  });
}

通过使用承诺,你可以使用.then为你的功能。具体如下

deleteRows(req.body.rows).then(function(result){
  // your logic
})

类似的你也可以使用promise来添加记录。

第二种方法:您也可以使用async await执行相同的操作async await documentation

deleteRows: async function(rows) {

    var result = await rows.forEach((row) => {
        models.TABLE.destroy({
                where: {
                    CNTRY_CD: row['CNTRY_CD'],
                    AREA_ID: row['AREA_ID'],
                    BUS_DT: row['BUS_DT']
                }
            })
            .then((region, err) => {
                return region
            });
    });

}

答案 1 :(得分:0)

对于错误:

未处理拒绝TimeoutError:ResourceRequest超时未处理拒绝SequelizeHostNotFoundError:无法连接到主机

这可以帮助您捕获Promise.all函数中的错误。你可以使用如下。

const a = Promise.resolve(1);
const b = Promise.reject(new Error(2));
const c = Promise.resolve(3);

Promise.all([a, b, c].map(p => p.catch(e => e)))
  .then(results => console.log(results)) // 1,Error: 2,3
  .catch(e => console.log(e));