React-ReduxとExpressでBigQueryからデータを取得するAPIを作りました。株価のアプリを作ろうと思い、その過程を記事にしている備忘録となります。
セットアップ
必要なモジュールやテーブルなどを準備します。
必要なモジュール
BigQueryのクライアントライブラリを追加します。
yarn add @google-cloud/bigquery
前提
下記の記事で追加したモジュールを前提にしてます。
React-ReduxとExpressでイベント一覧を取得表示する - case-kの備忘録
BigQueryに登録するデータは下記の記事でスクレイピングしたもの使います。
GitHub上にあるCSVを落とし、BigQueryにテーブルを作ります。
Selenium+Chrome Driverで日経平均株価をスクレイピング - case-kの備忘録
クライアントライブラリでAPIを作る
BigQueryからデータを取得するAPIを定義します。サービスアカウントキーを参照するパスはフルパスにする必要があります。
const logger = require('../logger'); const {BigQuery} = require('@google-cloud/bigquery'); const StockPriceHandler = class StockPriceHandler { constructor() { this.bigqueryClient = new BigQuery({ projectId: '', keyFilename: '' }); } selectBigQuery(query) { return new Promise((resolve, reject) => { const options = { query, // Location must match that of the dataset(s) referenced in the query. // location:'US', }; this.bigqueryClient.query(options, (err, rows) => { if (err) { return reject(err); } return resolve(rows); }); }); } /** * 日経平均株価を取得する * @param {*} req * @param {*} res */ searchNikkeiStockAverage(req, res) { const query = `SELECT date, year, month, day, unixtime_jst, opening_price, high_price, low_price, end_price FROM stock_app.stock_sample`; const options = { query, // Location must match that of the dataset(s) referenced in the query. // location:'US', }; const results = this.selectBigQuery(query).then((result) => { console.log(result); return res.json(result) }).catch((err) => { console.log(err); res.status(400).send(err.message); }); return results } } exports.StockPriceHandler = StockPriceHandler;
アクションからAPIを実行
アクションからAPIを実行しデータを取得します。
import axios from 'axios' export const READ_EVENTS = 'READ_EVENTS' export const readEvents = () => async dispatch => { const response = await axios.get('/events/searchNikkeiStockAverage') dispatch({ type: READ_EVENTS, response }) }
取得したデータはreducerでactionを元に状態遷移させ、コンポーネントを使い表示させてみます。
# reducer export default (events=[], action) => { switch (action.type) { case READ_EVENTS: return _.mapKeys(action.response.data, 'day') default: return events } }
ストアの状態はpropsでコンポーネントに渡し可視化させてみます。
# components render() { return ( <React.Fragment> <LineSeriesGraph events={this.props.events}/> <LineDrawing events={this.props.events}/> </React.Fragment> ) }