创build或更新Sequelize

我在我的Nodejs项目中使用Sequelize,我发现一个问题,我很难解决。 基本上我有一个cron从服务器获取对象的数组,而不是将其作为对象插入到我的数据库(对于这种情况下,漫画)。 但是,如果我已经有一个对象,我必须更新它。

基本上我有一个对象的数组,可以使用BulkCreate()方法。 但是当Cron重新开始的时候,它并不能解决问题,所以我需要使用一个upsert真正的标志进行某种更新。 主要问题:我必须有一个callback,所有这些创build或更新后才会触发一次。 有没有人有一个想法,我该怎么做? 迭代一个对象数组..创build或更新它,然后得到一个单一的callback后?

感谢您的关注

从文档中 ,只要有对象,就不需要查询执行更新的位置。 另外,诺言的使用应该简化callback:

履行

 function upsert(values, condition) { return Model .findOne({ where: condition }) .then(function(obj) { if(obj) { // update return obj.update(values); } else { // insert return Model.create(values); } } }) } 

用法

 upsert({ first_name: 'Taku' }, { id: 1234 }).then(function(result){ res.status(200).send({success: true}); }); 

注意

  1. 这个操作不是primefaces的
  2. 创build2个networking电话

这意味着重新考虑这种方法是可取的,并且可能只是在一个networking调用中更新值,并且可以:

  1. 看看返回的值(即rows_affected)并决定要做什么
  2. 如果更新操作成功,则返回成功。 这是因为资源是否存在不在这个服务的责任之内。

你可以使用upsert它更容易。

实施细节:

MySQL – 作为单个查询实现INSERT值ON DUPLICATE KEY
UPDATE值PostgreSQL – 作为exception处理的临时函数实现:INSERT EXCEPTION WHERE unique_constraint UPDATE
SQLite –作为两个查询实现INSERT; UPDATE。 这意味着无论行是否已经存在,都会执行更新

这可能是一个古老的问题,但这是我所做的:

 var updateOrCreate = function (model, where, newItem, onCreate, onUpdate, onError) { // First try to find the record model.findOne({where: where}).then(function (foundItem) { if (!foundItem) { // Item not found, create a new one model.create(newItem) .then(onCreate) .catch(onError); } else { // Found an item, update it model.update(newItem, {where: where}) .then(onUpdate) .catch(onError); ; } }).catch(onError); } updateOrCreate( models.NewsItem, {title: 'sometitle1'}, {title: 'sometitle'}, function () { console.log('created'); }, function () { console.log('updated'); }, console.log); 

声音喜欢你想要在async.each中包装你的Sequelize调用。

我喜欢Ataik的想法,但是做得稍微短一些:

 function updateOrCreate (model, where, newItem) { // First try to find the record return model .findOne({where: where}) .then(function (foundItem) { if (!foundItem) { // Item not found, create a new one return model .create(newItem) .then(function (item) { return {item: item, created: true}; }) } // Found an item, update it return model .update(newItem, {where: where}) .then(function (item) { return {item: item, created: false} }) ; } } 

用法:

 updateOrCreate(models.NewsItem, {slug: 'sometitle1'}, {title: 'Hello World'}) .then(function(result) { result.item; // the model result.created; // bool, if a new item was created. }); 

可选:在这里添加error handling,但我强烈build议链接一个请求的所有承诺,并在最后有一个error handling程序。

 updateOrCreate(models.NewsItem, {slug: 'sometitle1'}, {title: 'Hello World'}) .then(..) .catch(function(err){}); 

这可以使用自定义事件发射器来完成。

假设你的数据在一个名为data的variables中。

 new Sequelize.Utils.CustomEventEmitter(function(emitter) { if(data.id){ Model.update(data, {id: data.id }) .success(function(){ emitter.emit('success', data.id ); }).error(function(error){ emitter.emit('error', error ); }); } else { Model.build(data).save().success(function(d){ emitter.emit('success', d.id ); }).error(function(error){ emitter.emit('error', error ); }); } }).success(function(data_id){ // Your callback stuff here }).error(function(error){ // error stuff here }).run(); // kick off the queries 

您可以使用findOrCreate ,然后update sequelize中的方法。 这里是一个与async.js的示例

 async.auto({ getInstance : function(cb) { Model.findOrCreate({ attribute : value, ... }).complete(function(err, result) { if (err) { cb(null, false); } else { cb(null, result); } }); }, updateInstance : ['getInstance', function(cb, result) { if (!result || !result.getInstance) { cb(null, false); } else { result.getInstance.updateAttributes({ attribute : value, ... }, ['attribute', ...]).complete(function(err, result) { if (err) { cb(null, false); } else { cb(null, result); } }); } }] }, function(err, allResults) { if (err || !allResults || !allResults.updateInstance) { // job not done } else { // job done }); }); 

这是一个简单的例子,更新deviceID – > pushToken映射或创build它:

 var Promise = require('promise'); var PushToken = require("../models").PushToken; var createOrUpdatePushToken = function (deviceID, pushToken) { return new Promise(function (fulfill, reject) { PushToken .findOrCreate({ where: { deviceID: deviceID }, defaults: { pushToken: pushToken } }) .spread(function (foundOrCreatedPushToken, created) { if (created) { fulfill(foundOrCreatedPushToken); } else { foundOrCreatedPushToken .update({ pushToken: pushToken }) .then(function (updatedPushToken) { fulfill(updatedPushToken); }) .catch(function (err) { reject(err); }); } }); }); };