Pg-promise 性能提升:ON CONFLICT
Pg-promise performance boost : ON CONFLICT
我正在尝试遵循 pg-promise 库作者推荐的性能模式 here。
基本上 Vitaly 建议使用插入来这样做:
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 ', Inserts(', ', 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 ()" +
" ON CONFLICT ON CONSTRAINT constraint_name" +
" DO UPDATE SET country_id=,collection_id=",
[Inserts(', , ',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 ()" +
" ON CONFLICT ON CONSTRAINT constraint_name" +
" DO UPDATE SET (application_id,country_id,collection_id) = ",
Inserts(', , ',requestParameters));
当然,它不符合 postgresql 的标准。
有办法实现吗?
谢谢!
我为 Performance Boost 文章编写了该示例以生成简单形式的多插入,仅此而已,这对文章来说已经足够了。
你在这里尝试做的事情有点复杂,显然 function Inserts(template, data)
没有那种逻辑。
我无法从头脑中告诉你需要做什么才能改变它以适应你的场景,但它可能会变得非常复杂,甚至可能根本不值得做。
幸运的是,您不必这样做。我一次又一次地被问到我最近发布的某些格式化助手 - helpers namespace。您需要更新到最新版本的库(当前为 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。
我正在尝试遵循 pg-promise 库作者推荐的性能模式 here。
基本上 Vitaly 建议使用插入来这样做:
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 ', Inserts(', ', 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 ()" +
" ON CONFLICT ON CONSTRAINT constraint_name" +
" DO UPDATE SET country_id=,collection_id=",
[Inserts(', , ',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 ()" +
" ON CONFLICT ON CONSTRAINT constraint_name" +
" DO UPDATE SET (application_id,country_id,collection_id) = ",
Inserts(', , ',requestParameters));
当然,它不符合 postgresql 的标准。
有办法实现吗?
谢谢!
我为 Performance Boost 文章编写了该示例以生成简单形式的多插入,仅此而已,这对文章来说已经足够了。
你在这里尝试做的事情有点复杂,显然 function Inserts(template, data)
没有那种逻辑。
我无法从头脑中告诉你需要做什么才能改变它以适应你的场景,但它可能会变得非常复杂,甚至可能根本不值得做。
幸运的是,您不必这样做。我一次又一次地被问到我最近发布的某些格式化助手 - helpers namespace。您需要更新到最新版本的库(当前为 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。