我正在尝试编写一个Nodejs文件,以循环浏览来自气象局JSON文件的700个天气预报。每个文件都包含特定气象站点在过去24小时内的许多天气观测值:air temp,gust_kmh等。对于每个文件,我想查找每个观测值的最小值/最大值/平均值(air_temp_min,air_temp_max,air_temp_avg )。然后,我想将此提交到MSSQL数据库。我打算每天执行一次此操作,因此每个位置观测值将在数据库中以多行作为一行输入。
我不熟悉异步操作,并且在将一个操作/功能/承诺链接到下一个操作或功能或超过最大侦听器方面一直遇到麻烦。
因此,我需要一个优雅或有效的建议或指导。我不介意使用哪个包,我尝试过请求,axios,mssql,乏味。我可以让他们全部单独工作一行,但不能以一种和谐的方式在一起工作。
起点是遍历每个站点的URL。这是一个示例。
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95767.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95772.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94650.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95774.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95754.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95747.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95779.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94774.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94781.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95770.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95758.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.99738.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94775.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94776.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94773.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95773.json,
http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94588.json
谢谢。
答案 0 :(得分:1)
因此,您可以使用模块请求(+ request-promise-native),mssql,然后使用lodash(用于聚合,例如最大,最小,平均)和时刻进行日期解析。这是一些示例代码,可以满足您的要求。
您需要运行以下cmd行以安装依赖项:
npm install mssql request request-promise-native lodash moment --save
现在关于安排调用,我建议也许只是设置一个安排好的任务,每天调用一次脚本(取决于您的操作系统)。
一些待办事项..也许要确保我们很好地关闭连接等,并在某些情况下阻止某些异常处理!
运行此命令后,我在数据库中看到以下行:
天气数据
timestamp |location_name |air_temp_max |air_temp_min |air_temp_avg
-----------------------------------------------------------------------------------------------------
2019-03-11 00:00:00.000 |Lake Macquarie - Cooranbong |32.4 |17.8 |23.1027777777778
2019-03-11 00:00:00.000 |Maitland Airport |33.9 |19.9 |24.4478260869565
2019-03-11 00:00:00.000 |Mangrove Mountain |30 |18.1 |22.3784722222222
2019-03-11 00:00:00.000 |Merriwa |34.8 |18.6 |25.4435897435898
2019-03-11 00:00:00.000 |Murrurundi Gap |31.4 |17.4 |23.3627906976744
2019-03-11 00:00:00.000 |Nelson Bay |26.4 |22.5 |24.7
2019-03-11 00:00:00.000 |Newcastle Nobbys |27.7 |21.1 |23.1243055555556
2019-03-11 00:00:00.000 |Newcastle University |26.8 |21.6 |24.2
2019-03-11 00:00:00.000 |Norah Head |29.5 |20.6 |23.3048611111111
2019-03-11 00:00:00.000 |Scone Airport |35.8 |20.4 |26.0236363636363
2019-03-11 00:00:00.000 |Singleton (Defence) |34.5 |20 |25.1141891891892
2019-03-11 00:00:00.000 |Tocal |33.6 |20 |24.7993055555556
2019-03-11 00:00:00.000 |Williamtown |31.5 |20.7 |23.6551724137931
2019-03-11 00:00:00.000 |Armidale |20.7 |19.8 |20.3
2019-03-11 00:00:00.000 |Armidale Airport |29.7 |13.9 |22.0801282051282
2019-03-11 00:00:00.000 |Glen Innes Airport |29.7 |15.1 |21.8228187919463
天气模式SQL
CREATE TABLE weather_data (
timestamp datetime,
location_name nvarchar(200),
air_temp_max float,
air_temp_min float,
air_temp_avg float,
);
节点代码:
index.js
const rp = require('request-promise-native');
const _ = require('lodash');
const sql = require('mssql');
const moment = require('moment');
const config = {
user: 'db_user', // Change as appropriate
password: 'pass', // Change as appropriate
server: 'localhost', // Change as appropriate
database: 'Weather',
port: 1433 // Default port, change as appropriate
}
let sqlConnPool = null;
const urlList = [
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95767.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95772.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94650.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95774.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95754.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95747.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95779.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94774.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94781.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95770.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95758.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.99738.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94775.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94776.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94773.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.95773.json',
'http://reg.bom.gov.au/fwo/IDN60801/IDN60801.94588.json'
];
async function downloadStationData() {
for(url of urlList) {
let res = await downloadAndSaveWeatherData(url);
console.log("Res: ", res);
}
}
sql.connect(config).then(pool => {
console.log("Connected to database...");
sqlConnPool = pool;
downloadStationData()
});
async function downloadAndSaveWeatherData(url) {
console.log("downloadAndSaveWeatherData: Downloading from: ", url);
let weatherData = await downloadWeatherData(url);
if (weatherData.observations && weatherData.observations.data && weatherData.observations.data.length > 0) {
console.log("downloadAndSaveWeatherData: Observations (count): ", weatherData.observations.data.length);
let processedData = processWeatherData(weatherData.observations.data);
console.log("downloadAndSaveWeatherData: processed data: ", processedData);
let writeResult = await writeWeatherDataToDatabase(processedData);
return { status: "OK"};
}
}
// Get max, min, average etc.
function processWeatherData(data) {
const result = {
timestamp: moment(data[0].aifstime_utc.substring(0,8)).toDate(),
location_name: data[0].name
};
const fields = ["air_temp"];
fields.forEach(field => {
result[`${field}_max`] = _.max(data.map(row => row[field])),
result[`${field}_min`] = _.min(data.map(row => row[field])),
result[`${field}_avg`] = _.mean(data.map(row => row[field]))
});
return result;
}
function downloadWeatherData(url) {
const options = { url: url, json: true, resolveWithFullResponse: true }
return rp(options).then((response) => response.body);
}
function writeWeatherDataToDatabase(processedData) {
const request = sqlConnPool.request()
return new Promise((resolve, reject) => {
request.input('timestamp', sql.DateTime, processedData.timestamp);
request.input('location_name', sql.NVarChar, processedData.location_name);
request.input('air_temp_max', sql.Float, processedData.air_temp_max);
request.input('air_temp_min', sql.Float, processedData.air_temp_min);
request.input('air_temp_avg', sql.Float, processedData.air_temp_avg);
request.query('insert into weather_data (timestamp, location_name, air_temp_max, air_temp_min, air_temp_avg) values (@timestamp, @location_name, @air_temp_max, @air_temp_min, @air_temp_avg)',
(err, result) => {
if (err) {
console.error("writeWeatherDataToDatabase: Error occurred: ", err);
reject(err);
} else {
resolve(result);
}
});
});
}