我在我的 Nodejs 项目中使用 Sequelize,我发现了一个我很难解决的问题。
基本上我有一个 cron 从服务器获取对象数组,然后将其作为对象插入到我的数据库中(对于这种情况,卡通)。但如果我已经拥有其中一个对象,我必须对其进行更新。
基本上我有一个对象数组,并且可以使用 BulkCreate() 方法。但是当 Cron 再次启动时,它并没有解决它,所以我需要一些带有 upsert true 标志的更新。主要问题是:在所有这些创建或更新之后,我必须有一个只触发一次的回调。有谁知道我该怎么做?迭代一个对象数组..创建或更新它,然后在之后获得一个回调?
感谢关注
从文档中,您无需查询
实施
2 3 4 5 6 7 8 9 10 11 | return Model .findOne({ where: condition }) .then(function(obj) { // update if(obj) return obj.update(values); // insert return Model.create(values); }) } |
用法
2 3 | res.status(200).send({success: true}); }); |
注意
这意味着建议重新考虑该方法,并且可能只更新一次网络调用中的值,并且:
你可以使用 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
2 3 4 5 6 7 8 9 10 11 12 | // 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 的想法,但把它缩短了一点:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 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} }) ; } } |
用法:
2 3 4 5 | .then(function(result) { result.item; // the model result.created; // bool, if a new item was created. }); |
可选:在此处添加错误处理,但我强烈建议将一个请求的所有Promise链接起来,并在最后有一个错误处理程序。
2 3 | .then(..) .catch(function(err){}); |
这可能是一个老问题,但这就是我所做的:
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 | // 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); |
它将尝试在第一个参数中通过哈希查找记录以更新它,如果找不到 - 然后将创建新记录
这里是sequelize测试中的使用示例
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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); }); }); |
这可以通过自定义事件发射器来完成。
假设您的数据位于名为 data.
的变量中
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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 映射,要么创建它:
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 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); }); } }); }); }; |
你可以在 sequelize 中使用
的示例
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 | 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 }); }); |
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
我正在尝试按0-9和a-z的顺序创建数字和字母列表。我有一组值value_array=['0','1','2','3','4','5','6','7','8','9','a','b','光盘','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','','u','v','w','x','y','z']和一个组合列表的数组,按顺序,这些数字可以产生x个字符,比方说三个list_array=[]和一个当前字母和数字组合的数组(在将它插入列表数组之前我会把它变成一个字符串,]current_combo['0','0','0']