Node.js で JSON データを BigQuery にインポートする

2021.05.11

吉川@広島です。

掲題の通り、 Node.js で JSON データを BigQuery にインポートする検証をしてみましたので共有します。

本記事の実施にあたり、

BigQuery に JSON 形式のファイルデータをロードする場合の挙動や制限事項を確認してみた

こちらのブログを大いに参考にさせて頂きました。ありがとうございます。

環境

  • Node.js 14.13.0
  • TypeScript 4.1.3
  • dotenv 8.2.0
  • @google-cloud/bigquery 5.6.0

データセットの作成

GCP メニューから BigQuery を選択し開きます。

本記事の目標はテーブルを作成しそこにデータを保存することですが、その前に BigQuery のデータセットというリソースを作成する必要があります。

データセットの概要

プロジェクト > データセット > テーブル のような階層構造になっており、データセットの位置づけは MySQL でいう Database に近いのかな、と思いました。

プロジェクト名の右にあるハンバーガーを押下して、「データセットを作成」を選択します。

データセット ID に任意の命名をします。今回は sample_dataset としました。入力したら「データセットを作成」ボタンを押下します。

これで作成できました。プロジェクトにぶら下がるデータセット一覧を見ると sample_dataset が追加されたことが確認できます。

サービスアカウントとキーの作成

GCP に慣れていないのでサービスアカウント周りの設定も備忘録を兼ねて記述します。

ローカル端末のプログラムから GCP リソースにアクセスするためにサービスアカウントを作成します。

まず、 IAM と管理 > サービスアカウント から 「サービスアカウントを作成」を押下します。

すると作成画面が開かれますので、任意のサービスアカウント名を入力し「作成」を押下します。

続いて「このサービスアカウントにプロジェクトへのアクセスを許可する」が開かれます。「ロールを選択」を押下するとロールを検索できるメニューが出ますので、検索欄に bigquery と入力します。そうすると「 BigQuery 管理者」というロールが出てくるので、今回はこれを紐付けます。

ロールを選択できたら「続行」を押下し、そのまま「完了」を押下します。

これでサービスアカウント作成は完了です。

IAM と管理 > サービスアカウント に戻ると、今回追加したサービスアカウントが確認できます。

次はキーを作成します。作成したサービスアカウントのハンバーガーアイコンを押下するとメニューが出てくるので、「鍵を管理」を選択します。

画面遷移するので、「鍵を追加」を押下し、「新しい鍵を追加」を選択します。

ポップアップが出てきますので、そのまま「作成」を押下します。

作成後、すぐにキーがダウンロードされます。機密情報ですので公開しないよう注意して扱いましょう。

TypeScript コードを書く

先程のキーをスクリプトファイルと同じ場所に配置します。繰り返しになりますが、間違って GitHub の公開リポジトリにアップロードするなどないように注意しましょう。

認証のスタートガイドによると、環境変数 GOOGLE_APPLICATION_CREDENTIALS にキーファイルの場所を指定すると読んでくれるようです。今回は dotenv ライブラリを使って環境変数をセットするので、下のような .env ファイルを作成しておきます。

# .env
GOOGLE_APPLICATION_CREDENTIALS="./my-sa-key.json"

Node.js から BigQuery へのアクセスは nodejs-bigquery を使います。以下の公式サンプルコードが参考になりました。

https://github.com/googleapis/nodejs-bigquery/blob/master/samples/loadLocalFile.js https://github.com/googleapis/nodejs-bigquery/blob/master/samples/loadJSONFromGCSAutodetect.js

また、 BiqQuery にインポートするテストデータを用意する必要があります。冒頭紹介の記事でも述べられていますが、

JSONL( LDJSON )じゃないとだめ

ということで、以下のような JSONL (JSON Lines) 形式のテキストファイルを作成しておきます。

// sample-data.jsonl

{ "id": 1, "name": "foo" }
{ "id": 2, "name": "bar" }
{ "id": 3, "name": "baz" }

そして実行する TypeScript コードが以下です。

import { BigQuery, JobLoadMetadata } from '@google-cloud/bigquery'
import * as dotenv from 'dotenv'

const main = async () => {
  dotenv.config()
  const bigQueryClient = new BigQuery()
  const metadata: JobLoadMetadata = {
    sourceFormat: 'NEWLINE_DELIMITED_JSON',
    autodetect: true, // スキーマ定義を autodetect する
    location: 'US',
  }
  const datasetId = 'sample_dataset' // 作成したデータセット名を指定
  const tableId = 'sample_table' // 作成されるテーブル名を指定 (命名は任意)
  const [job] = await bigQueryClient
    .dataset(datasetId)
    .table(tableId)
    .load('./sample-data.jsonl', metadata) // 読み込む対象のファイル場所を指定
  console.log(`Job ${job.id} completed.`)
}

main()

実行後、 BigQuery コンソールからデータセット下に新しくできたテーブルを選択し、「プレビュー」を押下すると、ちゃんとデータが入っていることがわかります。

まとめ

GCP はあまり経験がなく、手探り気味の検証となりましたが良い勉強になりました。スキーマを autodetect してインポートできるのは非常に楽ですね。

本文紹介以外の参考記事