1

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);
        ...

ただし、問題は、「ソース」関数内で、すべての変数が範囲外であることです。しかし、私が見た限りでは、その理由はよくわかりません。デバッグ中、それらは「使用できません」とだけ表示されます。

4

0 に答える 0