GoでBigQueryクライアントを実装してBigQueryからデータを取得する

GoでBigQueryクライアントを実装してBigQueryからデータを取ってくる

会社のある偉大な先輩は、以前こう言った。
「BigQueryは全人類が使えるようになるべきだ」と。

僕は、最近BigQueryの学習を始めた。
BigQueryの学習の一環として、BigQueryクライアントを実装してみた。

やること

GoのコードからBigQueryクライアントを実装してSQLを走らせ、データをローカルに取得して、コマンドラインに表示させる。

クライアントライブラリって何?

好みの言語から、Google Cloud APIsをHTTPに直接リクエストしたり、RPC callsしたりして使うためのライブラリ。
公式ドキュメント

準備

クライアントライブラリのインストー

BigQueryのクライアントライブラリを以下のコマンドでインストールする。

go get cloud.google.com/go/bigquery

認証

BigQueryのAPIを使用するためには、アカウント認証を行う必要があるので、それを行う。
以下のサイトが参考になる。

公式ドキュメント

FluentdでGoogle BigQueryにログを挿入してクエリを実行する

Google Cloud Platformをローカルから利用するための準備

BigQueryクライアントを使う

手順

BigQueryクライアントをGoで実装するためには、大まかに以下のような手順を踏む。

  1. 空のcontextを生成
  2. contextとprojectIDを元にBigQuery用のclientを生成
  3. Queryを生成
  4. Queryを読み込んで、resultを取得するためのIteratorを生成
  5. Iteratorを回して順次結果を取得

詳細は、コード中にコメントとして記述している

なお、以下の公式ドキュメントを参考にしている

package bigqueryのGoDoc

BigQuery クライアント ライブラリの公式ドキュメント

コード

package main

import (
    "cloud.google.com/go/bigquery"
    "context"
    "fmt"
    "google.golang.org/api/iterator"
    "log"
)

func main() {
    fetchBigQueryData()
}

// BigQueryで実行するためのSQL
const QUERY = `
SQL
`

func fetchBigQueryData() {
    // 空のcontextを生成
    ctx := context.Background()

    // プロジェクトのID
    projectID := "プロジェクトのID"

    // contextとprojectIDを元にBigQuery用のclientを生成
    client, err := bigquery.NewClient(ctx, projectID)

    if err != nil {
        log.Printf("Failed to create client:%v", err)
    }

    // 引数で渡した文字列を元にQueryを生成
    q := client.Query(QUERY)

    // 実行のためのqueryをサービスに送信してIteratorを通じて結果を返す
    // itはIterator
    it, err := q.Read(ctx)

    if err != nil {
        log.Println("Failed to Read Query:%v", err)
    }

    for {
        // BigQueryの結果から、中身を格納するためのBigQuery.Valueのsliceを宣言
        // BigQuery.Valueはinterface{}型
        var values []bigquery.Value

        // 引数に与えたvaluesにnextを格納する
        // Iteratorを返す
        // これ以上結果が存在しない場合には、iterator.Doneを返す
        // iterator.Doneが返ってきたら、forを抜ける
        err := it.Next(&values)
        if err == iterator.Done {
            break
        }

        if err != nil {
            log.Println("Failed to Iterate Query:%v", err)
        }

        fmt.Println(values)
    }

}

実際に簡単なQueryを投げるように実装してみた

今回は、BigQueryのコンソールにデフォルトで表示されるPublic Datasetsの中から bigquery-public-data:usa_namesのusa_1910_2013のデータを使用した。

このテーブルに対して、'Mary’という名前を持つデータを取得して、コマンドラインに表示する。

実装の流れは先ほどと全く変わらない。

今回は、BigQueryクライアントの実装を目的としているため、SQLは以下のようにかなり簡素なものになっている。

SQL

SELECT
  *
FROM
  [bigquery-public-data:usa_names.usa_1910_2013]
WHERE
  name = 'Mary'
LIMIT
  100

実装

package main

import (
    "cloud.google.com/go/bigquery"
    "context"
    "fmt"
    "google.golang.org/api/iterator"
    "log"
)

func main() {
    fetchBigQueryData()
}

// BigQueryで実行するためのSQL
const QUERY = `
SELECT  *
FROM [bigquery-public-data:usa_names.usa_1910_2013]
WHERE name = 'Mary'
LIMIT 10
`

func fetchBigQueryData() {
    // 空のcontextを生成
    ctx := context.Background()

    // プロジェクトのID
    projectID := "プロジェクトのID"

    // contextとprojectIDを元にBigQuery用のclientを生成
    client, err := bigquery.NewClient(ctx, projectID)

    if err != nil {
        log.Printf("Failed to create client:%v", err)
    }

    // 引数で渡した文字列を元にQueryを生成
    q := client.Query(QUERY)

    // 実行のためのqueryをサービスに送信してIteratorを通じて結果を返す
    // itはIterator
    it, err := q.Read(ctx)

    if err != nil {
        log.Println("Failed to Read Query:%v", err)
    }

    for {
        // BigQueryの結果から、中身を格納するためのBigQuery.Valueのsliceを宣言
        // BigQuery.Valueはinterface{}型
        var values []bigquery.Value

        // 引数に与えたvaluesにnextを格納する
        // Iteratorを返す
        // これ以上結果が存在しない場合には、iterator.Doneを返す
        // iterator.Doneが返ってきたら、forを抜ける
        err := it.Next(&values)
        if err == iterator.Done {
            break
        }

        if err != nil {
            log.Println("Failed to Iterate Query:%v", err)
        }

        fmt.Println(values)
    }

}

実行結果

[AK F 1912 Mary 9]
[AK F 1916 Mary 18]
[AK F 1918 Mary 27]
[AK F 1919 Mary 22]
[AK F 1923 Mary 26]
[AK F 1925 Mary 24]
[AK F 1926 Mary 39]
[AK F 1927 Mary 30]
[AK F 1930 Mary 35]
[AK F 1931 Mary 41]

参考にさせていただいたサイト

package bigqueryのGoDoc

BigQuery クライアント ライブラリの公式ドキュメント

Google BigQuery API へのリクエストを認証する

FluentdでGoogle BigQueryにログを挿入してクエリを実行する

Google Cloud Platformをローカルから利用するための準備

※ Qiitaでも同一記事を投稿している qiita.com