我在我的Nodejs项目中使用Sequelize,我发现了一个问题,我很难解决。 基本上我有一个cron从服务器获取一个对象数组,而不是将它作为对象插入我的数据库(对于这种情况,卡通)。但如果我已经拥有其中一个对象,我必须更新它。
基本上我有一个对象数组,可以使用BulkCreate()方法。但是当Cron再次启动时,它并没有解决它,因此我需要使用upsert true标志进行某种更新。主要问题:我必须有一个回调,在所有这些创建或更新之后只触发一次。有谁知道我该怎么做?迭代一个对象数组..创建或更新它然后在?
后得到一个回调感谢您的关注
答案 0 :(得分:43)
从docs开始,一旦拥有该对象,就不需要查询where
来执行更新。此外,使用promise应简化回调:
<强>实施强>
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 :(得分:10)
我喜欢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.
});
可选:在这里添加错误处理,但我强烈建议将一个请求的所有承诺链接起来,并在最后有一个错误处理程序。
updateOrCreate(models.NewsItem, {slug: 'sometitle1'}, {title: 'Hello World'})
.then(..)
.catch(function(err){});
答案 2 :(得分:9)
您可以使用upsert 这样更容易。
实施细节:
MySQL - 作为单个查询实现INSERT值ON DUPLICATE KEY
UPDATE值PostgreSQL - 作为临时函数实现 异常处理:当unique_constraint更新时INSERT EXCEPTION SQLite - 实现为两个查询INSERT; UPDATE。这意味着 无论行是否已存在,都会执行更新 <或者
答案 3 :(得分:8)
这可能是个老问题,但这就是我所做的:
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);
答案 4 :(得分:2)
声音喜欢你想在async.each内包装你的Sequelize电话。
答案 5 :(得分:1)
这可以使用自定义事件发射器完成。
假设您的数据位于名为data的变量中。
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
答案 6 :(得分:0)
您可以在续集中使用findOrCreate
然后使用update
方法。这是一个带有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
});
});
答案 7 :(得分:0)
以下是更新deviceID - &gt;的简单示例pushToken映射或创建它:
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);
});
}
});
});
};
答案 8 :(得分:0)
User.upsert({ a: 'a', b: 'b', username: 'john' })
它将尝试在第一个参数中通过哈希查找记录以对其进行更新,如果找不到,则将创建新记录
Here是连续测试中的用法示例
it('works with upsert on id', function() {
return this.User.upsert({ id: 42, username: 'john' }).then(created => {
if (dialect === 'sqlite') {
expect(created).to.be.undefined;
} else {
expect(created).to.be.ok;
}
this.clock.tick(1000);
return this.User.upsert({ id: 42, username: 'doe' });
}).then(created => {
if (dialect === 'sqlite') {
expect(created).to.be.undefined;
} else {
expect(created).not.to.be.ok;
}
return this.User.findByPk(42);
}).then(user => {
expect(user.createdAt).to.be.ok;
expect(user.username).to.equal('doe');
expect(user.updatedAt).to.be.afterTime(user.createdAt);
});
});