Knexjs如果不存在,请插入其他更新

Uro*_*arc 5 knex.js

如何优化此代码?我不想在哪里打电话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();
        }
    });
Run Code Online (Sandbox Code Playgroud)

Seb*_*ddd 9

假设您有一个唯一键(本例中为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);
    })
}
Run Code Online (Sandbox Code Playgroud)

并像这样调用它:

insertOrUpdate('posts', [ 
    { post_id : 1, content: 'Blog Post 1' },
    { post_id : 2, content: 'Blog Post 2' } 
]);
Run Code Online (Sandbox Code Playgroud)


mat*_*sad 9

不确定何时添加,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
  })
Run Code Online (Sandbox Code Playgroud)


Rom*_*man 5

只是修复了@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)
    })
}
Run Code Online (Sandbox Code Playgroud)


Sin*_*nux 3

尝试ON DUPLICATE KEY UPDATE使用原始 sql,因为 knex 目前不支持此功能。

请参阅: https: //github.com/tgriesser/knex/issues/701