使用 KnexJS 查询 X 个表?
Using KnexJS to query X number of tables?
我这里有一个独特的情况,我无法以优雅的方式解决。
用户传递了一组他们想要为其导出数据的信号。这个数组可以是 1 -> Any_Number 所以首先我根据传递的信号获取 table 名称(每个信号将数据存储在单独的 table 中)并将它们存储在一个对象中。
下一步是遍历该对象(其中包含我需要查询的 table 个名称),按 table 执行查询并将结果存储在将传递的对象中到 Promise 中的下一个链。我没有在网上看到任何处理此问题的好方法的示例,但我知道这是一个相当独特的场景。
我在尝试添加对信号数组的支持之前的代码如下:
exports.getRawDataForExport = function(data) {
return new Promise(function(resolve, reject) {
var getTableName = function() {
return knex('monitored_parameter')
.where('device_id', data.device_id)
.andWhere('internal_name', data.param)
.first()
.then(function(row) {
if(row) {
var resp = {"table" : 'monitored_parameter_data_' + row.id, "param" : row.display_name};
return resp;
}
});
}
var getData = function(runningResult) {
return knexHistory(runningResult.table)
.select('data_value as value', 'unit', 'created')
.then(function(rows) {
runningResult.data = rows;
return runningResult;
});
}
var createFile = function(runningResult) {
var fields = ['value', 'unit', 'created'],
csvFileName = filePathExport + runningResult.param + '_export.csv',
zipFileName = filePathExport + runningResult.param + '_export.gz';
var csv = json2csv({data : runningResult.data, fields : fields, doubleQuotes : ''});
fs.writeFileSync(csvFileName, csv);
// create streams for gZipping
var input = fs.createReadStream(csvFileName);
var output = fs.createWriteStream(zipFileName);
// gZip
input.pipe(gzip).pipe(output);
return zipFileName;
}
getTableName()
.then(getData)
.then(createFile)
.then(function(zipFile) {
resolve(zipFile);
});
});
}
显然这对单个 table 来说效果很好,我已经更新了 getTableName() 和 createFile() 方法来处理数据数组,所以这个问题只与 getData() 方法有关。
干杯!
这种问题绝非独一无二,只要处理得当,就可以很简单地解决。
不要重写三个内部函数中的任何一个。
只需从 .getRawDataForExport()
中清除 explicit promise construction antipattern,使其 returns 成为一个自然发生的承诺并将异步错误传播给调用者。
return getTableName()
.then(getData)
.then(createFile);
现在,.getRawDataForExport()
是您的多个 "gets" 的基本组成部分。
然后,设计选择;并行与顺序操作。两者都有很好的记录。
并行:
exports.getMultiple = function(arrayOfSignals) {
return Promise.all(arrayOfSignals.map(getRawDataForExport));
};
顺序:
exports.getMultiple = function(arrayOfSignals) {
return arrayOfSignals.reduce(function(promise, signal) {
return promise.then(function() {
return getRawDataForExport(signal);
});
}, Promise.resolve());
};
首先,为了获得最佳的潜在性能,请尝试并行。
如果服务器在并行操作时阻塞或可能永远阻塞,请选择顺序。
我这里有一个独特的情况,我无法以优雅的方式解决。
用户传递了一组他们想要为其导出数据的信号。这个数组可以是 1 -> Any_Number 所以首先我根据传递的信号获取 table 名称(每个信号将数据存储在单独的 table 中)并将它们存储在一个对象中。
下一步是遍历该对象(其中包含我需要查询的 table 个名称),按 table 执行查询并将结果存储在将传递的对象中到 Promise 中的下一个链。我没有在网上看到任何处理此问题的好方法的示例,但我知道这是一个相当独特的场景。
我在尝试添加对信号数组的支持之前的代码如下:
exports.getRawDataForExport = function(data) {
return new Promise(function(resolve, reject) {
var getTableName = function() {
return knex('monitored_parameter')
.where('device_id', data.device_id)
.andWhere('internal_name', data.param)
.first()
.then(function(row) {
if(row) {
var resp = {"table" : 'monitored_parameter_data_' + row.id, "param" : row.display_name};
return resp;
}
});
}
var getData = function(runningResult) {
return knexHistory(runningResult.table)
.select('data_value as value', 'unit', 'created')
.then(function(rows) {
runningResult.data = rows;
return runningResult;
});
}
var createFile = function(runningResult) {
var fields = ['value', 'unit', 'created'],
csvFileName = filePathExport + runningResult.param + '_export.csv',
zipFileName = filePathExport + runningResult.param + '_export.gz';
var csv = json2csv({data : runningResult.data, fields : fields, doubleQuotes : ''});
fs.writeFileSync(csvFileName, csv);
// create streams for gZipping
var input = fs.createReadStream(csvFileName);
var output = fs.createWriteStream(zipFileName);
// gZip
input.pipe(gzip).pipe(output);
return zipFileName;
}
getTableName()
.then(getData)
.then(createFile)
.then(function(zipFile) {
resolve(zipFile);
});
});
}
显然这对单个 table 来说效果很好,我已经更新了 getTableName() 和 createFile() 方法来处理数据数组,所以这个问题只与 getData() 方法有关。
干杯!
这种问题绝非独一无二,只要处理得当,就可以很简单地解决。
不要重写三个内部函数中的任何一个。
只需从 .getRawDataForExport()
中清除 explicit promise construction antipattern,使其 returns 成为一个自然发生的承诺并将异步错误传播给调用者。
return getTableName()
.then(getData)
.then(createFile);
现在,.getRawDataForExport()
是您的多个 "gets" 的基本组成部分。
然后,设计选择;并行与顺序操作。两者都有很好的记录。
并行:
exports.getMultiple = function(arrayOfSignals) {
return Promise.all(arrayOfSignals.map(getRawDataForExport));
};
顺序:
exports.getMultiple = function(arrayOfSignals) {
return arrayOfSignals.reduce(function(promise, signal) {
return promise.then(function() {
return getRawDataForExport(signal);
});
}, Promise.resolve());
};
首先,为了获得最佳的潜在性能,请尝试并行。
如果服务器在并行操作时阻塞或可能永远阻塞,请选择顺序。