まさひlog

趣味で行っていることをのんびりとログとして残していきます

RustでBigQueryにあるデータを取得してみる

最近BigQueryには慣れてきたが、何らかのプログラムから操作する機会がなかったため、Rustで操作してみました

環境

Rust: 1.51

ライブラリ
https://github.com/Byron/google-apis-rs/tree/main/gen/bigquery2

サービスアカウント

今回RustからBigQueryに接続するための認証としてサービスアカウントを使用します。

お試しのため、ロールは「BigQuery 管理者」を付与しています。
作成したサービスアカウントからJSONで鍵を作成、ファイル名をauth.jsonに変更し、Rustプロジェクト直下におきます。

BigQuery

sample_1という名前のテーブルを作成し、
適当に2レコードほどデータを入れています f:id:mshr_t:20210604230841p:plain

実装

ライブラリのリファレンスを参考に進めていこうと思います

必要ライブラリの記入

[package]
name = "app"
version = "0.1.0"
authors = []
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
google-bigquery2 = "*"
hyper = "^0.14"
hyper-rustls = "^0.22"
serde = "^1.0"
serde_json = "^1.0"
yup-oauth2 = "^5.0"
tokio = { version = "1.6.1", features = ["full"] } # #[tokio::main]を使うために入れている

コード

projectId,datasetIdやテーブルは必要に応じて変更してください。

use bigquery2::Error;
use hyper;
use hyper_rustls;
use yup_oauth2 as oauth2;
use google_bigquery2 as bigquery2;

#[tokio::main]
async fn main() {
    let secret = oauth2::read_service_account_key(&"auth.json".to_string()).await.unwrap(); // 認証ファイルの読み込み
    let key = oauth2::ServiceAccountAuthenticator::builder(secret).build().await.unwrap();

    let hub = bigquery2::Bigquery::new(hyper::Client::builder().build(hyper_rustls::HttpsConnector::with_native_roots()), key);

    let mut req = bigquery2::api::QueryRequest::default();
    req.query = Some("SELECT * FROM `projectId.datasetId.sample_1`".to_string()); // 実行したいSQL
    req.use_legacy_sql = Some(false); // standardSQLを使うためfalseに
    let result = hub.jobs().query(req, "projectId")
                 .doit().await;
    
    match result {
        Err(e) => match e {
             Error::HttpError(_)
            |Error::Io(_)
            |Error::MissingAPIKey
            |Error::MissingToken(_)
            |Error::Cancelled
            |Error::UploadSizeLimitExceeded(_, _)
            |Error::Failure(_)
            |Error::BadRequest(_)
            |Error::FieldClash(_)
            |Error::JsonDecodeError(_, _) => println!("{}", e),
        },
        Ok(res) => {
            let query_res: bigquery2::api::QueryResponse = res.1;
            println!("Success: {:?}", query_res.rows.unwrap())
        },
    }
}

結果

以下のようにテーブルの中身が取れました!
TableCellはString型で定義されているため、実際に使うとなると少し工夫は必要そうです。

Success: [TableRow { f: Some([TableCell { v: Some("2") }, TableCell { v: Some("fuga") }]) }, TableRow { f: Some([TableCell { v: Some("1") }, TableCell { v: Some("hoge") }]) }] 

まとめ

今回はRustでBigQueryにあるデータを取得してみました。 個人的にRustでGCPサービスに接続すること自体初めてだったため、 サービスアカウントによる認証方法を探すのにyup-oauth2のコードを見ていて時間がかかってしまいました。。

他の機能も色々あるのでこれから試してみようと思います!

参考

github.com

github.com