Create or Update Sequelize
我在我的 Nodejs 项目中使用 Sequelize,我发现了一个我很难解决的问题。
基本上我有一个 cron 从服务器获取对象数组,然后将其作为对象插入到我的数据库中(对于这种情况,卡通)。但如果我已经拥有其中一个对象,我必须对其进行更新。
基本上我有一个对象数组,并且可以使用 BulkCreate() 方法。但是当 Cron 再次启动时,它并没有解决它,所以我需要一些带有 upsert true 标志的更新。主要问题是:在所有这些创建或更新之后,我必须有一个只触发一次的回调。有谁知道我该怎么做?迭代一个对象数组..创建或更新它,然后在之后获得一个回调?
感谢关注
从文档中,您无需查询
实施
1
2 3 4 5 6 7 8 9 10 11 |
用法
1
2 3 |
注意
这意味着建议重新考虑该方法,并且可能只更新一次网络调用中的值,并且:
你可以使用 upsert
这更容易。
Implementation details:
- MySQL – Implemented as a single query
INSERT values ON DUPLICATE KEY UPDATE values - PostgreSQL – Implemented as a temporary function with exception handling:
INSERT EXCEPTION WHEN unique_constraint UPDATE - SQLite – Implemented as two queries
INSERT; UPDATE . This means that the update is executed regardless of whether the row already
existed or not- MSSQL – Implemented as a single query using
MERGE and WHEN (NOT) MATCHED THEN Note that SQLite returns undefined for created, no
matter if the row was created or updated. This is because SQLite
always runsINSERT OR IGNORE + UPDATE , in a single query, so there
is no way to know whether the row was inserted or not.
现在使用 async/await 更新 07/2019
1
2 3 4 5 6 7 8 9 10 11 12 |
async function updateOrCreate (model, where, newItem) {
// First try to find the record const foundItem = await model.findOne({where}); if (!foundItem) { // Item not found, create a new one const item = await model.create(newItem) return {item, created: true}; } // Found an item, update it const item = await model.update(newItem, {where}); return {item, created: false}; } |
我喜欢 Ataik 的想法,但把它缩短了一点:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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} }) ; } } |
用法:
1
2 3 4 5 |
可选:在此处添加错误处理,但我强烈建议将一个请求的所有Promise链接起来,并在最后有一个错误处理程序。
1
2 3 |
这可能是一个老问题,但这就是我所做的:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
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); |
1
|
它将尝试在第一个参数中通过哈希查找记录以更新它,如果找不到 – 然后将创建新记录
这里是sequelize测试中的使用示例
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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.findByPk(42); |
这可以通过自定义事件发射器来完成。
假设您的数据位于名为 data.
的变量中
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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 |
听起来您想将 Sequelize 调用package在 async.each 中。
这是一个简单的例子,它要么更新 deviceID -> pushToken 映射,要么创建它:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
var Promise = require(‘promise’); var PushToken = require("../models").PushToken; var createOrUpdatePushToken = function (deviceID, pushToken) { |
你可以在 sequelize 中使用
的示例
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
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 }); }); |
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/271049.html