case-kの備忘録

日々の備忘録です

React-ReduxとExpressでBigQueryからデータを取得するAPIを作る

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の備忘録

f:id:casekblog:20200210161013p:plain:w400

サービスアカウントキー

GCPのコンソールよりサービスアカウントキーを発行します。キーには役割として「BigQuery データ閲覧者 」と「BigQuery ジョブユーザー」を付与しました。本番等で使う場合はデータセットレベルまで権限を絞る必要があります。

クライアントライブラリで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>
  )
}

Highcharts Reactで日経平均株価を表示する - case-kの備忘録
f:id:casekblog:20200210154352p:plain