node.js 续集更新插入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29063232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sequelize upsert
提问by Hussein Al-Far
i need to get the id for the inserted/updated record when using .upsert()in sequelize.
.upsert()在 sequelize 中使用时,我需要获取插入/更新记录的 ID。
right now .upsert()returns a boolean indicating whether the row was created or updated.
现在.upsert()返回一个布尔值,指示该行是创建还是更新。
return db.VenueAddress.upsert({
addressId:address.addressId,
venueId: venue.venueId,
street: address.street,
zipCode: address.zipCode,
venueAddressDeletedAt: null
}).then(function(test){
//test returned here as true or false how can i get the inserted id here so i can insert data in other tables using this new id?
});
回答by Matt Ringer
I don't think that returning the upserted record was available when the OP asked this question, but it has since been implemented with this PR. As of Sequelize v4.32.1, you can pass a boolean returningas a query param to select between returning an array with the record and a boolean, or just a boolean indicating whether or not a new record was created.
我认为当 OP 提出这个问题时,返回 upserted 的记录是不可用的,但它已经通过这个PR实现了。从Sequelize v4.32.1 开始,您可以传递一个布尔值returning作为查询参数,以在返回带有记录的数组和一个布尔值之间进行选择,或者只是一个指示是否创建新记录的布尔值。
You do still need to provide the id of the record you want to upsertor a new record will be created.
您仍然需要提供要更新插入的记录的 ID,否则将创建新记录。
For example:
例如:
const [record, created] = await Model.upsert(
{ id: 1, name: 'foo' }, // Record to upsert
{ returning: true } // Return upserted record
);
回答by Ian Grainger
I wanted upsert to return the created or updated object. It doesn't because only PGSQL supports it directly, apparently.
我想要 upsert 返回创建或更新的对象。显然,这不是因为只有 PGSQL 直接支持它。
So I created a naive implementation that will - probably in a non-performant way, and possibly with all sorts of race conditions, do that:
所以我创建了一个幼稚的实现——可能以一种非性能的方式,并且可能在各种竞争条件下,做到这一点:
Sequelize.Model.prototype.findCreateUpdate = function(findWhereMap, newValuesMap) {
return this.findOrCreate({
where: findWhereMap,
defaults: findWhereMap
})
.spread(function(newObj, created) {
// set:
for(var key in newValuesMap) {
newObj[key] = newValuesMap[key];
}
return newObj.save();
});
};
Usage when trying to create/update a move in a game (contrived example alert!):
尝试在游戏中创建/更新移动时的用法(人为示例警报!):
models.Game
.findOne({where: {gameId: gameId}})
.then(function(game) {
return db.Move.findCreateUpdate(
{gameId: gameId, moveNum: game.moveNum+1},
{startPos: 'kr4', endPos: 'Kp2'}
);
});
回答by Omar Faroque Anik
This is what worked for me:
这对我有用:
Model.upsert({
title:your title,
desc:your description,
location:your locations
}).then(function (test) {
if(test){
res.status(200);
res.send("Successfully stored");
}else{
res.status(200);
res.send("Successfully inserted");
}
})
It will check db to find based on your primary key. If it finds then, it will update the data otherwise it will create a new row/insert into a new row.
它将根据您的主键检查数据库以查找。如果找到,它将更新数据,否则它将创建新行/插入新行。
回答by Matthew Chung
i know this is an old post, but in case this helps anyone
我知道这是一个旧帖子,但以防万一这有助于任何人
const upsert = async (model: any, values: any, condition: any): Promise<any> => {
const obj = await model.findOne({ where: condition })
if (obj) {
// only do update is value is different from queried object from db
for (var key in values) {
const val = values[key]
if (parseFloat(obj[key]) !== val) {
obj.isUpdatedRecord = true
return obj.update(values)
}
}
obj.isUpdatedRecord = false
return obj
} else {
// insert
const merged = { ...values, ...condition }
return model.create(merged)
}
}
回答by Hussein Al-Far
janmeier said:
janmeier 说:
This is only supported by postgres, so to keep the API consistent across dialects this is not possible.
这仅由 postgres 支持,因此要在方言之间保持 API 一致,这是不可能的。
please see : https://github.com/sequelize/sequelize/issues/3354
回答by decoder7283
I believe my solution is the most up to date with most minimal coding.
我相信我的解决方案是最新的,编码最少。
const SequelizeModel = require('sequelize/lib/model')
SequelizeModel.upsert = function() {
return this.findOne({
where: arguments[0].where
}).then(obj => {
if(obj) {
obj.update(arguments[0].defaults)
return
}
return this.create(arguments[0].defaults)
})
}
回答by slifty
It isn't using upsert, but .bulkCreatehas an updateOnDuplicateparameter, which allows you to update certain fields (instead of creating a new row) in the event that the primary key already exists.
它不使用 upsert,但.bulkCreate有一个updateOnDuplicate参数,它允许您在主键已经存在的情况下更新某些字段(而不是创建新行)。
MyModel.bulkCreate(
newRows,
{
updateOnDuplicate: ["venueId", ...]
}
)
I believe this returns the resulting objects, and so I think this might enable the functionality you're looking for?
我相信这会返回结果对象,所以我认为这可能会启用您正在寻找的功能?
回答by thanh1101681
Which I myself resolved as follows:
我自己解决如下:
return db.VenueAddress.upsert({
addressId:address.addressId,
venueId: venue.venueId,
street: address.street,
zipCode: address.zipCode,
venueAddressDeletedAt: null
},{individualHooks: true}).then(function(test){
// note individualHooks
});

