使用Sequelize在一系列项目上创建/更新

时间:2014-10-31 20:24:23

标签: node.js promise bluebird sequelize.js

我创建了一个函数:

  • 采取一系列标签'并查看他们是否已在数据库中有记录
  • 创建那些不存在的,
  • 并更新现有的
  • 返回报告每个项目的json数组,无论是更新/创建还是导致错误

我设法让它发挥作用,但我觉得我只是做了一些丑陋的狗'晚餐!

var models = require("../models");
var Promise = models.Sequelize.Promise;

module.exports = {

    addBeans: function (req, callback) {

        Promise.map(req.body.beansArr, function (bean) {
            return models.Portfolio.findOrCreate({where: {label: bean}}, {label: bean});

        }).then(function (results) {   // Array of 'instance' and 'created' for each bean "findOrCreate(where, [defaults], [options]) -> Promise<Instance>"
            var promisesArr = [];
            results.forEach(function (result) {
                if (result[1]) {   // result[1] = wasCreated
                    promisesArr.push(Promise.resolve([result[0].dataValues.label, "created"]));   
                } else {
                    promisesArr.push(
                        models.Portfolio.update({label: result[0].dataValues.label},
                            {where: {label: result[0].dataValues.label}}).then(function () {
                                return Promise.resolve([result[0].dataValues.label, "updated"])
                            })
                    );
                }
            }); 
            return promisesArr;

        // When it's all done create a JSON response
        }).then(function (results) {
            var resultObj = {items: []};  // JSON to return at the end
            Promise.settle(results).then(function (promiseinstances) {

                for (var i = 0; i < promiseInstances.length; i++) {
                    if (promiseInstances[i].isFulfilled()) {
                        resultObj.items.push({
                            item: {
                                label: promiseInstances[i].value()[0],
                                result: promiseInstances[i].value()[1],
                                error: ''
                            }
                        });
                    }
                    else if (promiseInstances[i].isRejected()){
                        resultObj.items.push({
                            label: promiseInstances[i].value()[0],
                            result: 'error',
                            error: promiseInstances[i].reason()
                        });
                    }
                }

            // Send the response back to caller
            }).then(function () {
                return callback(null, resultObj);
            }, function (e) {
                return callback(e, resultObj);
            });

        });
    }

};

问题:

  • 使用Sequelize创建/更新值有更简单或更明显的方法吗?
  • 我对Promise.settle()的使用是否适用于此案例?我觉得我把它变得比它需要的更复杂。

我是Sequelize的新手并使用Promises,如果有人可以就此提出建议我会很感激。

3 个答案:

答案 0 :(得分:4)

我觉得这样可以在CodeReview.SE上运行得更好,但我可以看到一些问题。

  

使用Sequelize创建/更新值有更简单或更明显的方法吗?

嗯,一方面:

.then(function(array){
   var newArr = [];
   array.forEach(function(elem){
       newArr.push(fn(elem);
   }
   return newArr;
});

只是

.map(fn)

此外,承诺会同化,因此您可以return val; .then return Promise.resolve(val);).then(function (results) { // Array of 'instance' and 'created' for each bean "findOrCreate(where, [defaults], [options]) -> Promise<Instance>" var promisesArr = []; results.forEach(function (result) { if (result[1]) { // result[1] = wasCreated promisesArr.push(Promise.resolve([result[0].dataValues.label, "created"])); } else { promisesArr.push( models.Portfolio.update({label: result[0].dataValues.label}, {where: {label: result[0].dataValues.label}}).then(function () { return Promise.resolve([result[0].dataValues.label, "updated"]) }) ); } }); return promisesArr; })

所以:

.map(function(result){
     if(result[1]) return [result[0].dataValues.label, "created"];
     return  models.Portfolio.update({label: result[0].dataValues.label},
                    {where: {label: result[0].dataValues.label}}).
                    return([result[0].dataValues.label, "updated"]);
 });

只是

.then(function(results){
     return results.map(function(result){
     if(result[1]) return [result[0].dataValues.label, "created"];
     return  models.Portfolio.update({label: result[0].dataValues.label},
                    {where: {label: result[0].dataValues.label}}).
                    return([result[0].dataValues.label, "updated"]);
 });
 });

但是,既然您希望它能够解决,无论解决方案如何,您都必须这样做:

.settle()

这意味着无论如何都会解决,然后您拨打.settle().then(function(results){ // your settle logic here });

}).then(function () {
    return callback(null, resultObj);
}, function (e) {
    return callback(e, resultObj);
});

注意最后一个:

.nodeify(callback);

简单地说:

{{1}}

但是,我建议坚持承诺。

答案 1 :(得分:0)

我使用Promise.settle作为sequelize.update,并且可以通过_settledValueField来影响行号。

promise.push(...update...)

db.sequelize.Promise.settle(promise).then(function (allresult) {
    var affectcnt = 0
    allresult.forEach(function (singlecnt) {
      if (undefined !== singlecnt._settledValueField[1]) {
        affectcnt += parseInt(singlecnt._settledValueField[1])
      }
    })

不幸的是,它只能用于更新。

答案 2 :(得分:0)

您可以使用sequelize在数据库中插入数组。您要更改如下模型。我正在尝试通过数组在数据库中添加多种语言。

language: { type: DataTypes.STRING, 
          allowNull: false,
          get() 
         { 
         return this.getDataValue('language').split(';') 
         }, 
        set(val)
        {
        this.setDataValue('language',Array.isArray(val) ? val.join(','):val);

      }
  }