Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

当記事の内容

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では動きません。 

shuichiro
社内の研修を企画したり、新しいものを試したりしています。 悩んだことを残していこうと思います。 投稿する記事の内容は個人の意見であり、所属する企業の見解を代表するものではありません。
japan-systems
「2019年に50周年を迎えたIT企業です。最先端の技術により全国の企業、官公庁、自治体に多くの実績があります。」
https://www.japan-systems.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした