Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequelize correctly executing multiple creates + updates

I have a cron job that scrapes a list of items on a website and then inserts or updates records in a database. When I scrape the page, I want to create records for new ones that haven't been created yet, otherwise update any existing ones. Currently I'm doing something like this:

// pretend there is a "Widget" model defined

function createOrUpdateWidget(widgetConfig) {
    return Widget.find(widgetConfig.id)
        .then(function(widget) {
            if (widget === null) {
                return Widget.create(widgetConfig);
            }
            else {
                widget.updateAttributes(widgetConfig);
            }
        });
}

function createOrUpdateWidgets(widgetConfigObjects) {
    var promises = [];

    widgetConfigObjects.forEach(function(widgetConfig) {
        promises.push(createOrUpdateWidget(widgetConfig));
    });

    return Sequelize.Promise.all(promises);
}


createOrUpdateWidgets([...])
    .done(function() {
        console.log('Done!');
    });

This seems to work fine, but I'm not sure if I'm doing this "correctly" or not. Do all promises that perform DB interactions need to run serially, or is how I have them defined ok? Is there a better way to do this kind of thing?

like image 752
chinabuffet Avatar asked Nov 09 '14 19:11

chinabuffet


People also ask

How to use the update() method in Sequelize?

The update () method is the Sequelize way of generating and executing an UPDATE statement. When you need to update multiple rows with the same value, you need to add a where option with the right condition to update the rows. For example, suppose you want to update the status of all rows as active. You can use the following update () method:

How do I use the updateonduplicate option?

The updateOnDuplicate option accepts an array of values. you need to put the name of the attribute (or column) you wish to update as a string inside the array. If you want to update both firstName and status columns, then you can add the firstName attribute into the updateOnDuplicate array:

How do I update multiple rows in a table in SQL?

If you need to update with different values for each/ some of the rows, you need to use the bulkCreate () method. Although the bulkCreate () method is used to INSERT many rows to the table, it has the updateOnDuplicate option to update your rows when there’s a conflict to perform the insert.


1 Answers

What you're doing is pretty idiomatic and perfectly fine, the only room for improvement is to utilize the fact Sequelize uses Bluebird for promises so you get .map for free, which lets you convert:

function createOrUpdateWidgets(widgetConfigObjects) {
    var promises = [];

    widgetConfigObjects.forEach(function(widgetConfig) {
        promises.push(createOrUpdateWidget(widgetConfig));
    });

    return Sequelize.Promise.all(promises);
}

Into:

function createOrUpdateWidgets(widgetConfigObjects) {
    return Sequelize.Promise.map(widgetConfig, createOrUpdateWidget)
}

Other than that minor improvement - you're chaining promises correctly and seem to have the correct hang of it.

like image 113
Benjamin Gruenbaum Avatar answered Oct 04 '22 00:10

Benjamin Gruenbaum