1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

BigQueryのRemote FunctionsでAPIから直接データを取得する

Posted at

やりたいこと

タイトルの通り。

動機

とあるAPIから取得できるデータ(ex. 実行ログとか)をBigQueryで分析できるようにしたい。
いままでは専用のジョブを作ったりしてたけど、そもそもBQで直接取れるのでは?と思ったのと、軽く検索した感じ同じようなことやってる人が見つからなかったのでやってみた。

BigQuery Remote Functionsとは

BigQuery リモート関数を使用すると、SQL と JavaScript 以外の言語や、BigQuery ユーザー定義関数で許可されていないライブラリやサービスを使用して関数を実装できます。

ドキュメントのサンプルでは「引数の数値を足し算したものを返す」関数の例がある。
もっと色々できるはずだと思ったので、思いついたのが今回のもの。

必要なもの

  • BigQuery
  • Cloud Functions(Cloud Run Functions)
    • Cloud Runでもよい
  • なんらかのJSONを返すAPI
    • 今回はGitHubのAPIを使ってみた

実装

Cloud Functions

ソースコード

適当に書いた。サンキューChatGPT。

import requests
import functions_framework
from flask import jsonify, request

@functions_framework.http
def get_github_repos(request):
    # POSTリクエストのJSONボディから`username`を取得
    request_json = request.get_json(silent=True)
    calls = request_json["calls"]
    replies = []
    print("==debug==")
    print(calls)
    print("==debug==")
    for call in calls:
        # GitHub APIのURL
        url = f"https://api.github.com/users/{call[0]}/repos"
        print(f"call {url}")
        response = requests.get(url)

        # GitHub APIからのレスポンスを処理
        if response.status_code == 200:
            repos = response.json()
            replies.append(repos)
        else:
            return jsonify({"error": "Failed to fetch repositories"}), response.status_code

    return jsonify({"replies": replies})

Functionsの設定

ポイントだけ。

  • リージョン: us-central1
    • BigQueryのデータセットをマルチリージョンにしちゃったので、USから適当に選んだ。
    • データセットを単一リージョンにしてTokyoとかを選べば、FunctionもTokyoでいけると思う。
  • 権限: bqcx-xxxp@gcp-sa-bigquery-condel.iam.gserviceaccount.com に起動元ロール(Cloud Functions 起動元)をつける
    • このサービスアカウントは、後でBigQuery Remote Functionsを作成したときに自動生成されるもの。

BigQuery

Remote Functions

https://cloud.google.com/bigquery/docs/remote-functions?hl=ja#create_a_remote_function
上記を参考に設定

関数を作るDDLは以下のような感じ。

CREATE FUNCTION `PROJECT_ID`.DATASET_ID.get_api(x STRING) RETURNS JSON
REMOTE WITH CONNECTION `PROJECT_ID.us.api-functions`
OPTIONS (
  endpoint = 'https://us-central1-PROJECT_ID.cloudfunctions.net/get-api-1'
)

実行

image.png

とれた。

おわりに

  • とりあえず適当に書いたけど思った通りのことができた。使いみちあるかなあ。
    • 本気で使うなら、APIバカスカ実行しないようにキャッシュなりを実装しないといけない。
    • Functions側のIP固定もしたいだろうからVPCサービスコネクタあたりが必要そう。
    • ゴリッと取ってきた値を1行に入れてるから、本当は要素ごとに行は分けたい。
  • Remote Functionsはもっといろんな使い道があると思うんだがなかなか使いこなせてない。
1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?