nodejs アプリで pgpromise を使用しています。私が行っていることの 1 つは、10000 を超える多くのレコードをアップサートすることです。私がこれを行っていた元の方法は、db.tx を使用してバッチを返すことです。このアプローチの唯一の問題は、1 つは時間がかかること、2 つは大量の Promise を配列にロードし、大量のメモリを消費することです。
これが私が現在していることです...
var worksheet = workbook.getWorksheet(1);
return db.tx(function (t) {
var insertStatements = [];
var upsertProcessedData = this.getSql('./sql/upsertProcessedData.sql');
for (var i = 2; i <= worksheet._rows.length; i++) {
// need to convert strings to dates for postgres insert
// console.log('Working row ' + i);
worksheet.getRow(i).getCell(8).value = new Date(worksheet.getRow(i).getCell(8).value);
// here we create a new array from the worksheet, as we need a 0 index based array.
// the worksheet values actually begins at element 1. We will splice to dump the undefined element at index 0.
// This will allow the batch promises to work correctly... otherwise everything will be offset by 1
var arrValues = Array.from(worksheet.getRow(i).values);
arrValues.splice(0, 1);
// these queries are upsert. Inserts will occur first, however if they error on the constraint, an update will occur instead.
insertStatements.push(this.one(upsertProcessedData, arrValues));
}
console.log('Begin inserts');
return t.batch(insertStatements);
}).then( blah blah blah...)
このアプローチは機能しますが、データの大きなワークシートを取得すると、非常に遅くなります。
私はつまずいて使用しsequence
ましたが、それがどのように機能するかを理解するのに苦労しています. ドキュメントによると、そのように使用するように記載されています..
function source(index, data, delay) {
// must create and return a promise object dynamically,
// based on the index of the sequence;
switch (index) {
case 0:
return this.query('select 0');
case 1:
return this.query('select 1');
case 2:
return this.query('select 2');
}
// returning or resolving with undefined ends the sequence;
// throwing an error will result in a reject;
}
db.tx(function (t) {
// `t` and `this` here are the same;
return this.sequence(source);
})
ワークシート内のデータへの「ソース」関数のアクセスを許可する方法がわかりません。ソース関数の「データ」パラメータはどこから来るのですか? ワークシート obj をソース関数に渡すことはできないようです。
むしろ、シーケンスアプローチを試してみたいのですが、SQLを含むクエリファイルにアクセスする方法と、このシーケンス関数を使用してワークシートを反復処理する方法がわかりません...
編集:したがって、Vitalyがシーケンスについて書いたことを読み、githubの問題を見た後、私が思いついたのは次のとおりです。
Promise.bind(promiseBindObject)
.then(function (workbook) {
return this.workbook.xlsx.readFile(this.fileName);
}).then(function (workbook) {
var worksheet = workbook.getWorksheet(1);
// console.log(worksheet.name);
var upsertProcessedRqData = db.getSql('./sql/upsertProcessedRqData.sql');
function source(index, data, delay) {
// create and return a promise object dynamically,
// based on the index passed;
var arrValues = worksheet.getRow(index).values;
if (index < worksheet._rows.length) {
return this.this.one(upsertProcessedRqData, arrValues);
}
// returning or resolving with undefined ends the sequence;
// throwing an error will result in a reject;
}
db.tx(function (t) {
return t.sequence(source);
...
ただし、問題は、「ソース」関数内で、すべての変数が範囲外であることです。しかし、私が見た限りでは、その理由はよくわかりません。デバッグ中、それらは「使用できません」とだけ表示されます。