如何优化此代码? 我不想在那里打电话2次......是否有可能有更好的查询?
return self.db.clientDevices.where(device).then(function (rows) {
if (rows.length != 1) {
device.key = value;
self.db.clientDevices.insert(device).then();
} else {
self.db.clientDevices.where(device).update(device).then();
}
});
答案 0 :(得分:3)
不确定是什么时候添加的,knex 现在有一个 onConflict
方法:http://knexjs.org/#Builder-merge。我以这种方式编写了一个“upsert”函数,它似乎与 mysql 一起工作正常:
module.exports = (table, idKey, data) => require('../knex')(table)
.insert(data)
.onConflict(idKey)
.merge()
.catch( err => {
console.error(`There was an error upserting the "${table}" table by ${idKey}:`, err)
throw err
})
答案 1 :(得分:2)
使用原始sql尝试ON DUPLICATE KEY UPDATE
,因为knex现在不支持此功能。
答案 2 :(得分:2)
假设您有一个唯一键(在此示例中为 post_id )和一个对象数组( blogPosts ),则可以使用以下帮助方法:
function insertOrUpdate(tableName, blogPosts){
return knex.transaction(trx => {
let queries = blogPosts.map(tuple =>
trx.raw(util.format('%s ON CONFLICT (post_id) DO UPDATE SET %s',
trx(tableName).insert(tuple).toString().toString(),
trx(tableName).update(tuple).whereRaw(`'${tableName}'.post_id = '${tuple.post_id}'`).toString().replace(/^update\s.*\sset\s/i, '')
))
.transacting(trx)
);
return Promise.all(queries).then(trx.commit).catch(trx.rollback);
})
}
并这样调用它:
insertOrUpdate('posts', [
{ post_id : 1, content: 'Blog Post 1' },
{ post_id : 2, content: 'Blog Post 2' }
]);
答案 3 :(得分:2)
只需修复@Sebyddd正则表达式,删除格式并将逻辑从“ ON CONFLICT”更改为“ ON DUPLICATE KEY UPDATE”: https://gist.github.com/hinex/017c7c98c4a163d766fe2191a65fd944
const insertOrUpdate = (tableName, rows) => {
return DB.transaction((trx) => {
const queries = rows.map((tuple) => {
const insert = trx(tableName).insert(tuple).toString()
const update = trx(tableName).update(tuple).toString().replace(/^update(.*?)set\s/gi, '')
return trx.raw(`${insert} ON DUPLICATE KEY UPDATE ${update}`).transacting(trx)
})
return Promise.all(queries).then(trx.commit).catch(trx.rollback)
})
}
答案 4 :(得分:0)
如果您使用的是PostgreSQL
,因为没有ON DUPLICATE KEY UPDATE
。因此,在PostgreSQL
中,您应该使用ON CONFLICT ("id") DO UPDATE SET
:
const insertOrUpdate = (knex, tableName, data) => {
const firstData = data[0] ? data[0] : data;
return knex().raw(
knex(tableName).insert(data).toQuery() + ' ON CONFLICT ("id") DO UPDATE SET ' +
Object.keys(firstData).map((field) => `${field}=EXCLUDED.${field}`).join(', ')
);
};
如果您使用Objection.js
(knex的包装器),那么(在这种情况下,请不要忘记导入knex):
const insertOrUpdate = (model, tableName, data) => {
const firstData = data[0] ? data[0] : data;
return model.knex().raw(
knex(tableName).insert(data).toQuery() + ' ON CONFLICT ("id") DO UPDATE SET ' +
Object.keys(firstData).map((field) => `${field}=EXCLUDED.${field}`).join(', ')
);
};