この記事に関して
BigQuery + Lambda + CloudWatch を利用して、APIから取得したデータをBigQueryに保存するバッチを実装する機会があり、Node.jsでBigQueryのテーブル作成、テーブルにInsertする方法を書き残したいなと思います。
環境
node v12.18.4
TypeScript
サービスアカウントを作成する
BigQueryへのアクセス権を取得するため、GCPのコンソールからサービスアカウントを作成します。
サービスアカウントのトークンを使用して、GCPのリソースとGoogleCloudAPIsへのアクセスが可能になります。
サービスアカウントのコンソールから秘密鍵を作成し、取得します。
※サービスアカウントとはリソースと同等なので、安全に管理できているか常に気をつける必要があります。
公式ドキュメントでサービスアカウント保護、使用と管理のベストプラクティスが公開されています。
サービス アカウントの使用と管理のベスト プラクティス
サービス アカウントを保護するためのベスト プラクティス
Node.jsから @google-cloud/bigquery
を使用する
npm install @google-cloud/bigquery
取得したサービスアカウントの秘密鍵を使用してBigQueryにアクセスする
import { BigQuery } from "@google-cloud/bigquery";
...
const bigQueryClient = new BigQuery({
credentials: {
private_key: your_service_account_private_key,
client_email: your_service_account_client_email
},
projectId: your_gcp_project_id
});
対象データセットに対してテーブルを作成
BigQueryはテーブルをパーティションしないとフルスキャンになるため、パフォーマンス向上のためパーティション分割テーブルを今回の実装では作成しました。
// テーブルの存在確認をして、存在しなかったら作成
const isTableExist = await bigQueryClient
.dataset(dataSetId)
.table(tableId)
.exists();
const options = {
schema: schema,
location: your_locaiton,
timePartitioning: {
type: "DAY"
}
};
await bigQueryClient.dataset(dataSetId).createTable(tableId, options);
作成したテーブルに対してデータをインサートする
await bigQueryClient
.dataset(dataSetId)
.table(tableId)
.insert(data);
注意した点
負荷を減らすため、APIからデータを取得するたびにテーブルにインサートするのではなく、APIからある程度まとまったデータセットを取得してからインサート処理を実行するようにし、インサート回数ができるだけ少なくなるよう注意しました。
参考文献
https://cloud.google.com/bigquery/docs/reference?hl=ja
https://cloud.google.com/bigquery/docs/partitioned-tables?hl=ja
https://github.com/googleapis/nodejs-bigquery