Create / update with Sequelize on an array of elements

I created a function for:

  • take an array of "labels" and see if they have a db entry already
  • create ones that don't exist,
  • and update the ones that exist
  • returns a json array report for each item, no matter if they were updated / created or an error occurred.

I managed to get it to work, but I feel like I just made an ugly dog ​​dinner!

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

        });
    }

};

      

Question:

  • Is there an easier or more obvious way to create / update values ​​using Sequelize?
  • Am I using use Promise.settle()

    for this case? I have a feeling that I made this more difficult than it should be.

I am new to Sequelize and am using Promises, I would appreciate if anyone could advise on this.

+3


source to share


2 answers


I feel like this works better on CodeReview.SE, but I see a couple of problems.

Is there an easier or more obvious way to create / update values ​​using Sequelize?

Firstly:

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

      

Just



.map(fn)

      

In addition, Promises assimilated, so you can return val;

to .then

have return Promise.resolve(val);

.

So:

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

      

Just



.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"]);
 });

      

However, since you want it to work regardless of its resolution, you will need to:

.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"]);
 });
 });

      

This means that it will be resolved independently, then you call .settle()

:

.settle().then(function(results){
     // your settle logic here
});

      

Note that the latter:

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

      

Just:

.nodeify(callback);

      

However, I recommend sticking with promises.

+4


source


I am using Promise.settle for sequelize.update and can get the line number value on _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])
      }
    })

      



Unfortunately it only works for updating.

0


source







All Articles