web-dev-qa-db-ja.com

KnexJSでのアップサート

私はPostgreSQLにupsertクエリがあります:

INSERT INTO table
  (id, name)
values
  (1, 'Gabbar')
ON CONFLICT (id) DO UPDATE SET
  name = 'Gabbar'
WHERE
  table.id = 1

このアップサートクエリにknexを使用する必要があります。これについてどうやって行くの?

15
myusuf

だから私は次の提案を使ってこれを解決しました Knexの問題のページでのDotnilの回答

var data = {id: 1, name: 'Gabbar'};
var insert = knex('table').insert(data);
var dataClone = _.cloneDeep(data);

delete dataClone.id;

var update = knex('table').update(dataClone).whereRaw('table.id = ' + data.id);
var query = util.format('%s ON CONFLICT (id) DO UPDATE SET %s',
  insert.toString(),
  update.toString().replace(/^update\s.*\sset\s/i, '')
);

return knex.raw(query)
.then(function(dbRes){
  // stuff
});

これが誰かを助けることを願っています。

7
myusuf

私が考えることができるさらに別のアプローチ!

exports.upsert = (t, tableName, columnsToRetain, conflictOn) => {
    const insert = knex(tableName)
        .insert(t)
        .toString();
    const update = knex(tableName)
        .update(t)
        .toString();
    const keepValues = columnsToRetain.map((c) => `"${c}"=${tableName}."${c}"`).join(',');
    const conflictColumns = conflictOn.map((c) => `"${c.toString()}"`).join(',');
    let insertOrUpdateQuery = `${insert} ON CONFLICT( ${conflictColumns}) DO ${update}`;
    insertOrUpdateQuery = keepValues ? `${insertOrUpdateQuery}, ${keepValues}` : insertOrUpdateQuery;
    insertOrUpdateQuery = insertOrUpdateQuery.replace(`update "${tableName}"`, 'update');
    insertOrUpdateQuery = insertOrUpdateQuery.replace(`"${tableName}"`, tableName);
    return Promise.resolve(knex.raw(insertOrUpdateQuery));
};
1

私はこれを行うための関数を作成しました knex githubの問題のページで説明されています (複合固有のインデックスを処理するための落とし穴とともに)。

0
Tim