LoginSignup
15
6

More than 5 years have passed since last update.

Goで実装してGoogle Cloud FunctionsからBigQueryへデータを追加する

Posted at

当記事の内容

Google Cloud FunctionsをGoで実装してHTTPリクエストを受け取りBigQueryへデータを追加する方法を記載します。

開発環境

  • Google Cloud Shellを使用
  • 以下のコマンドを実施済
$ sudo gcloud components update && gcloud components install beta
  • Google Cloud Functions APIは有効化済
  • Go:1.11

事前準備

BigQueryのテーブル作成

始めにBigQueryのテーブルを準備します。
テーブルの定義は以下の通りです。

names.json
[
 {
   "description": "名前",
   "name": "NAME",
   "type": "String",
   "mode": "Required"
 },
 {
   "description": "時刻",
   "name": "DATETIME",
   "type": "Timestamp",
   "mode": "Nullable"
 }
]

bqコマンドを使ってテーブルを作成します。

$ bq mk DATASET
Dataset 'YOUR_PROJECT:DATASET' successfully created.
$ bq mk --table DATASET.NAMES names.json
Table 'YOUR_PROJECT:DATASET.NAMES' successfully created.

実装とデプロイ

Fucntionsプログラムの実装

Functionsで動作させるプログラムを作成していきます。
GETリクエストが送られてきた際に"name"パラメータを取得してBigQueryへ出力しています。
GCPが提供している"cloud.google.com/go/bigquery"ライブラリを用いてBigQueryへ出力しています。リクエストパラメータに加え現在時刻を付与しています。

FunctionsToBigQuery.go
package functions

import (
        "context"
        "fmt"
        "log"
        "net/http"
        "os"
        "time"

        //BigQueryの操作に必要なライブリ
        "cloud.google.com/go/bigquery"
)

//BigQueryにデータを追加するための構造体、タグで変数とキーを紐づける
type Data struct {
        Name     string    `bigquery:"NAME"`
        Datetime time.Time `bigquery:"DATETIME"`
}

//HTTPトリガーで実行される
func FunctionsToBigQuery(w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodGet: //GETの場合

                //GETパラメータの"name"から値を取り出す
                names, err := r.URL.Query()["name"]

                //取り出せない場合はエラーとして処理を終了する
                if !err || len(names[0]) < 1 {
                        fmt.Fprint(w, "パラメータに\"name\"がありません。\r\n")
                        return
                }

                //BigQueryeへ出力する関数を呼び出す
                WriteToBigQuery(names[0])

        default: //GET以外の場合はエラー
                http.Error(w, "405 - Method Not Allowed", http.StatusMethodNotAllowed)
        }
}

func WriteToBigQuery(name string) {

        //流し込むデータを構造へ格納する
        data := Data{}
        data.Name = name
        data.Datetime = time.Now()

        //コンテキストを取得する
        ctx := context.Background()

        //プロジェクトIDを取得する
        projectID := os.Getenv("GCP_PROJECT")

        //BigQueryを操作するクライアントを作成する、エラーの場合はLoggingへ出力する
        client, err := bigquery.NewClient(ctx, projectID)
        if err != nil {
                log.Printf("BigQuery接続エラー Error:%T message: %v", err, err)
                return
        }

        //deferでクライアントを閉じる
        defer client.Close()

        //クライアントからテーブルを操作するためのアップローダーを取得する
        u := client.Dataset("DATASET").Table("NAMES").Uploader()

        items := []Data{data}

        //テーブルへデータの追加を行う、エラーの場合はLoggingへ出力する
        err = u.Put(ctx, items)
        if err != nil {
                log.Printf("データ書き込みエラー Error:%T message: %v", err, err)
                return
        }
}

モジュールの用意

次のgo.modを準備します。"cloud.google.com/go/bigquery"を使用しているので、必要なライブラリに追加します。バージョンは0.36.01を指定します。

go.mod
module functions

go 1.11

require cloud.google.com/go v0.36.0

デプロイ

プログラムの準備が出来たらデプロイをしていきます。
gcloud functions deployコマンドを実行すると3分くらいでデプロイが完了します。

$ gcloud functions deploy FunctionsToBigQuery --runtime go111 --trigger-http 
(略)
status: ACTIVE
timeout: 60s
(略)

テスト

curlで実際にGETリクエストを送信してみます。リクエストを送るエンドポイントはデプロイした時のログに出ていますので探します。

$ curl https://us-central1-YOUR_PROJECT.cloudfunctions.net/FunctionsToBigQuery?name=aaaaa

次にbqコマンドでクエリを発行しデータが追加されいていることを確認します。

$ bq query "SELECT * FROM DATASET.NAMES LIMIT 10"
Waiting on bqjob_XXXXXXXXXXXXXXXX_XXXXXXXXXXX_1 ... (0s) Current status: DONE   
+-------+---------------------+
| NAME  |      DATETIME       |
+-------+---------------------+
| aaaaa | 2019-03-24 04:38:06 |
+-------+---------------------+

最後に

簡単にBigQueryへ書き込むREST APIが作成できました。あまりアクセス数の多くないアンケートフォームやキャンペーンサイトにも使えそうです。
2019/4/14の技術書典6に"Goで学ぶGoogleCloudFunctions"という本を頒布します。興味ある人は是非是非おこしください。サークルサイトはこちらです。


  1. 2019/3/25現在0.37.1が最新ですが。Go1.12が必要になるためGoogle Cloud Functionsでは動きません。 

15
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
6