20
19

More than 5 years have passed since last update.

BigQuery の API を Ruby から扱う bigquery-client という gem を作りました。

もともと BigQuery の gem といえば abronte/BigQuery があったんですが、個人的に欲しい機能がなかったのと、当時所属していたプロジェクトでは BigQuery を多用していて、もっと汎用的なものが必要だったので新しく作ることにしました。

インストール

% gem install bigquery-client

基本的な使い方

require "bigquery-client"

client = BigQuery::Client.new(
  project:                "your-project-42",
  dataset:                "your_dataset",
  email:                  "1234567890@developer.gserviceaccount.com",
  private_key_path:       "/path/to/keyfile.p12",
  private_key_passphrase: "notasecret",
  auth_method:            "private_key"
)

client.sql "SELECT * FROM publicdata:samples.wikipedia LIMIT 10"

INSERT

BigQuery::Client#insertを使うとレコードの INSERT ができます。内部的には Streaming Insert (insertAll) を使用しています。

client.insert("table_name", nickname: "john", age: 42)

# 配列で渡せば複数行をまとめて insert できる
rows = [
  { nickname: "foo", age: 43 },
  { nickname: "bar", age: 44 }
]
client.insert("table_name", rows)

CREATE TABLE

テーブルを作成します。

schema = [
  { name: "foo", type: "timestamp" },
  { name: "bar", type: "string"    }
]
client.create_table("new_table_name", schema)

SELECT

手軽に SELECT したい場合は BigQuery::Client#sql を使うのが良いです。

client.sql "SELECT * FROM dataset_name.table_name LIMIT 100"

BigQuery には INTEGER, STRING, BOOLEAN, FLOAT, TIMESTAMP といったデータ型がありますが、BigQuery::Client#sql はこれらのカラムをパースして、ハッシュの配列に詰めて結果を返します。

client.sql "SELECT born_alive_alive,is_male,weight_pounds FROM publicdata:samples.natality LIMIT 2"
#=> [{"born_alive_alive"=>0, "is_male"=>true, "weight_pounds"=>8.437090766739999}, {"born_alive_alive"=>2, "is_male"=>true, "weight_pounds"=>6.8122838958}]

tables

データセット内にあるテーブルの一覧を返します。

client.tables
#=> ["your_table", "your_table2", "your_table3"]

fetch_schema

テーブル名を指定してスキーマを取得します。

client.fetch_schema("table_name")
#=> [{"name"=>"nickname", "type"=>"STRING"}, {"name"=>"age", "type"=>"INTEGER"}]

DELETE

テーブル名を指定してテーブルを削除します。

client.delete_table('table_name')

Datasets API

bigquery-client はデータセットを扱う API もサポートしています。データセットを扱うだけならば:datasetを指定する必要はありません。

# `:dataset`は省いても OK
client = BigQuery::Client.new(
  project:                "your-project-42",
  email:                  "1234567890@developer.gserviceaccount.com",
  private_key_path:       "/path/to/keyfile.p12",
  private_key_passphrase: "notasecret",
  auth_method:            "private_key"
)

# データセットの一覧を取得
client.datasets
#=> ["your_dataset", "your_dataset2"]

# データセットを作成
client.create_dataset('dataset_name')

# データセットを削除
client.delete_dataset('dataset_name')

Projects API

プロジェクトを扱う API もサポートしています。プロジェクトを扱うだけならば:dataset:projectを指定する必要はありません。

# `:dataset`と`:project`は省いても OK
client = BigQuery::Client.new(
  email:                  "1234567890@developer.gserviceaccount.com",
  private_key_path:       "/path/to/keyfile.p12",
  private_key_passphrase: "notasecret",
  auth_method:            "private_key"
)

# プロジェクトの一覧を取得
client.projects
#=> ["your_project"]

豆知識

bigquery-client は手軽に扱えることを重視して開発しました。例えば BigQuery::Client#datasets は API のレスポンスに含まれる、おそらくは普通の用途では使用しないであろう情報を落として、データセット名だけをただの文字列の配列として返すようになっています。

client.datasets #=> ["your_dataset", "your_dataset2"]

ですが、例えば bigquery-client を使用した gem を作る場合など、突っ込んだ用途で使用する場合には、BigQuery::Client#datasets が捨ててしまう一部の情報が必要になる場合もあるかと思います。そういった用途のために、bigquery-clietnt には API を叩いて素のレスポンスを返すだけのメソッドを別途用意してあります。これらのメソッドも private になってはおらず、利用できます。

# 内部的には list_datasets を使用
def datasets
  list_datasets['datasets'].map {|dataset| dataset['datasetReference']['datasetId'] }
end

# こっちも public メソッド
def list_datasets
  access_api(
    api_method: bigquery.datasets.list
  )
end

ref. https://github.com/ttanimichi/bigquery-client/blob/9b24655e63d40551effacb82dceac7a3d8ba23b7/lib/bigquery-client/datasets.rb#L5-L13

お願い: 足りない機能は Pull Request ください

BigQuery の API にはエンドポイントが数多くあり、すべてのエンドポイントをサポートしたうえで各メソッドの使い勝手を改善していくのには結構な労力を必要としています。僕は僕自身が必要としている機能を優先的に作っているので、使い方によっては機能が足りない場合があるかもしれません。そういった場合は気軽に Pull Request を送ってもらえると嬉しいです :smiley:

20
19
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
20
19