Повышение производительности Pg-обещания: ON CONFLICT
Я пытаюсь следовать шаблону производительности, рекомендованному здесь автором библиотеки pg-обещания.
В основном Виталий рекомендует делать это со вставками:
var users = [['John', 23], ['Mike', 30], ['David', 18]];
// We can use Inserts as an inline function also:
db.none('INSERT INTO Users(name, age) VALUES $1', Inserts('$1, $2', users))
.then(data=> {
// OK, all records have been inserted
})
.catch(error=> {
// Error, no records inserted
});
Используя следующую вспомогательную функцию:
function Inserts(template, data) {
if (!(this instanceof Inserts)) {
return new Inserts(template, data);
}
this._rawDBType = true;
this.formatDBType = function () {
return data.map(d=>'(' + pgp.as.format(template, d) + ')').join(',');
};
}
Мой вопрос: как бы вы поступили, если на вкладыше есть противопоказание? Мой код:
db.tx(function (t) {
return t.any("SELECT... ",[params])
.then(function (data) {
var requestParameters = [];
async.each(data,function(entry){
requestParameters.push(entry.application_id,entry.country_id,collectionId)
});
db.none(
" INSERT INTO application_average_ranking (application_id,country_id,collection_id) VALUES ($1)" +
" ON CONFLICT ON CONSTRAINT constraint_name" +
" DO UPDATE SET country_id=$2,collection_id=$3",
[Inserts('$1, $2, $3',requestParameters),entry.country_id,collectionId])
.then(data=> {
console.log('success');
})
.catch(error=> {
console.log('insert error');
});
});
});
Очевидно, я не могу получить доступ к параметрам, потому что я вне цикла асинхронного.
Я также пытался сделать что-то вроде этого:
db.none(
" INSERT INTO application_average_ranking (application_id,country_id,collection_id) VALUES ($1)" +
" ON CONFLICT ON CONSTRAINT constraint_name" +
" DO UPDATE SET (application_id,country_id,collection_id) = $1",
Inserts('$1, $2, $3',requestParameters));
Но, конечно, это не соответствует стандарту postgresql.
Есть ли способ добиться этого?
Спасибо!
1 ответ
Я написал этот пример для статьи в Performance Boost, чтобы генерировать мульти-вставки в простой форме, не более того, что было достаточно для статьи.
То, что вы пытаетесь сделать здесь, немного сложнее, и, очевидно, function Inserts(template, data)
не имеет такой логики.
Я не могу сказать вам от всей души, что нужно сделать, чтобы изменить его, чтобы учесть ваш сценарий, но он может стать довольно сложным, и, возможно, даже не стоит делать это вообще.
К счастью, вам не нужно. Меня не раз спрашивали об определенных помощниках по форматированию, которые я выпустил совсем недавно - пространстве имен помощников. Вам необходимо обновить до самой последней версии библиотеки (в настоящее время 4.1.9), чтобы иметь возможность использовать ее так, как вам нужно.
Измените ваш пример на следующее:
var h = pgp.helpers;
var cs = new h.ColumnSet(['?application_id', 'country_id', 'collection_id'],
{table: 'application_average_ranking'});
db.tx(t => {
return t.any("SELECT... ", [params])
.then(function (data) {
var insertData = data.map(d => {
return {
application_id: d.application_id,
country_id: d.country_id,
collection_id: collectionId
};
});
var updateData = {
country_id: entry.country_id,
collection_id: collectionId
};
var query = h.insert(insertData, cs) +
" ON CONFLICT ON CONSTRAINT constraint_name DO UPDATE SET " +
h.sets(updateData, cs);
db.none(query)
.then(data => {
console.log('success');
})
.catch(error => {
console.log('insert error');
});
});
});
и это должно сделать это.
Смотрите также: ColumnSet.