Zenn
Open21

Firebase Data Connectを使ってみよう

かがんかがん

Firebase で RDB (PostgreSQL) が使えるData Connect
https://firebase.google.com/products/data-connect?hl=ja

今のところプレビュー版だけど、一旦使ってみる

これまで Firebase の中でDB使おうと思ったらFirestore (NoSQL) しかなかったので、早くGAしてほしい

かがんかがん

Blaze プランが必要

無料プランのSparkプランだと使わせてもらえない。
従量課金のBlazeプランに入る必要がある。

まあ多少はお金かかってもいいのでプランを上げる。
あとData Connectについては3ヶ月無料(?)的なことが書いてあったはず(スクショ撮っておけばよかった)
※正確な内容は各自お調べください

かがんかがん

注: Spark プラン プロジェクトで Data Connect を試す場合は、このローカルのクイックスタート ガイドをご覧ください。このガイドでは、エミュレータとローカル データベースを使用してローカルでプロトタイプを作成します。代わりに、Blaze プラン プロジェクトに Data Connect を追加してサービスと Cloud SQL データベースを設定する場合は、本番環境のスタートガイドをお試しください。
https://firebase.google.com/docs/data-connect/quickstart-local

ローカル環境のエミュレータで試すだけならSparkでも行けるらしい?

かがんかがん

VSCode拡張でセットアップするとファイルが作られる

├─.firebaserc
├─.gitignore
├─firebase.json
│
├─.firebase
│      .graphqlrc
│
└─dataconnect
    │  dataconnect.yaml
    │
    ├─.dataconnect
    │  └─schema
    │      │  prelude.gql
    │      │
    │      └─main
    ├─connector
    │      connector.yaml
    │      mutations.gql
    │      queries.gql
    │
    └─schema
            schema.gql
かがんかがん

スキーマ定義

https://firebase.google.com/docs/data-connect/quickstart-local?hl=ja#create_a_schema

スキーマは /dataconnect/schema/schema.gql のファイルで定義する。
セットアップ時に作られたファイルにはコメントアウトされた状態でサンプルコードが書いてあるので、コメントアウトを外す。

クエリ実行

https://firebase.google.com/docs/data-connect/quickstart-local?hl=ja#add_data_to_your_tables

拡張機能によって、 type の定義の上に「Add data」「Read Data」というボタンが現れる(便利の波動を感じる)
このボタンは「CodeLens ボタン」と言うらしい(この拡張機能に限った名前ではなく、コード中に挿入される表示が CodeLens っていうことなのかな?)

「Add data」を押すとインサートを実行するためのmutationが書かれたgqlファイルが生成される(お手軽~~~!)
保存すると dataconnect/MovieMetadata_insert.gql として保存される。
(保存しなくても、後述の実行は可能。というか、書き捨てになるので保存しなくていい)

「Add data」で生成されたファイル
# This is a file for you to write an un-named mutation. 
# Only one un-named mutation is allowed per file.
mutation {
  movieMetadata_insert(
    data: {id: "11111111222233334444555555555555", movieId: "11111111222233334444555555555555", description: "", rating: 0, releaseYear: 0}
  )
}

「Read data」も同様にqueryが書かれたファイルが作られる

「Read data」で生成されたファイル
# This is a file for you to write an un-named queries. 
# Only one un-named query is allowed per file.
query {
  movieMetadatas{
    movie {
      title
      imageUrl
      genre
    }
    rating
    releaseYear
    description
  }
}

この querymutation の上にも拡張機能によってボタンが現れており、localかproductionに対して実行できる(嬉しい~~~)

かがんかがん

クエリ定義

https://firebase.google.com/docs/data-connect/quickstart-local?hl=ja#define_your_query

アプリケーションで使用するクエリを /dataconnect/connector/queries.gql に定義する。
これもセットアップ時にサンプルコードがコメントアウトの状態で書いてあるのですぐ試せる。

query のコメントアウトを外すと CodeLensボタンが出るのでクリックするだけで実行できる

# @auth() directives control who can call each operation.
# Anyone should be able to list all movies, so the auth level is set to PUBLIC
query ListMovies @auth(level: PUBLIC) {
  movies {
    id
    title
    imageUrl
    genre
  }
}

@auth ディレクティブってもしかして Firebase Authと連携できる感じか…?
ここではPUBLICにしているから全部取れる的な?

疑問

定義したqueryはコードからはどうやって参照する?

後述。

@auth の levelってどう使う?

https://firebase.google.com/docs/data-connect/authorization-and-security?hl=ja#auth-directive

ディレクトリの connector とかの分け方の基準がよくわかってない

  • .dataconnect: Data Connect の機能によって自動生成されるファイル。.gitignore で除外されている
  • connector: SDKとの接続のための設定、クエリ・ミューテーション定義など。
  • schema: スキーマ定義。

ファイル命名の制約がどこまでかわからん

注: クエリとミューテーションは任意の .gql ファイルに配置できます。queries.gql や mutations.gql という名前にする必要はありません。
https://firebase.google.com/codelabs/firebase-dataconnect-web?hl=ja#1

つまり、サンプルコードでは例としてわかりやすくqueryとmutationで分けているけど、User, Movie, MovieMetadata みたいにエンティティごとにファイルを分けたり、使用するページごとで分けたりしてもいいわけだ

また、connectorのディレクトリを複数作ってもOK。

かがんかがん

リレーションシップ

サンプルコードの MovieMetadata には、 movie というフィールドがあり、これが Movie を参照している

type Movie @table {
  # ...
}

type MovieMetadata @table {
  movie: Movie! @unique # Movieを参照している
  # movieId: UUID <- this is created by the above reference
  rating: Float
  releaseYear: Int
  description: String
}

これにより、MovieをリストするときにMovieMetadataを引っ張って来れる(楽……)
movieMetadata_on_movie のように、 <field>_on_<foreign_key_field> の形式で自動生成されるらしい?

query ListMovies @auth(level: PUBLIC) {
  movies {
    id
    title
    imageUrl
    genre
    movieMetadata_on_movie {
        rating
    }
  }
}
かがんかがん

SDKを使う

https://firebase.google.com/docs/data-connect/quickstart-local?hl=ja#generate_sdks_and_use_them_in_your_app

VSCode拡張の「Add SDK to app」を実行で、SDKコードのサンプルができる。

src ディレクトリを選択すると、以下のような構造でファイルができる

src(指定したディレクトリ)
└─dataconnect-generated
    └─js
        └─default-connector
            │  index.cjs.js
            │  index.d.ts
            │  package.json
            │
            └─esm
                    index.esm.js
                    package.json

dataconnect/connector/connector.yaml にこういう設定ができる

connectorId: default
generate:
  javascriptSdk:
    outputDir: ../../src/dataconnect-generated/js/default-connector
    package: "@firebasegen/default-connector"
    packageJsonDir: ../../src

(多分この設定を変えれば適当にディレクトリは変えられるはず)

src/dataconnect-generated/js/default-connector というディレクトリが自動生成されたモジュールとなるので、これを参照することでクエリやミューテーションを呼び出すことができる。

スキーマやクエリ・ミューテーションの .gql ファイルの変更を監視して、自動的に書き出しを行ってくれるっぽい(さすが 👏)

VSCode以外の環境では、watchオプションつきのコマンドで自動反映できるらしい。
https://firebase.google.com/docs/data-connect/web-sdk?hl=ja#update_sdks_while_prototyping

かがんかがん

クライアントコードの書き方

https://firebase.google.com/docs/data-connect/web-sdk?hl=ja

クエリ・ミューテーションをData Connectにデプロイ→クライアントから呼び出し、という流れ。
あくまで実行されるのはサーバーサイド。

https://firebase.google.com/docs/data-connect/web-sdk?hl=ja#set-client

かがんかがん

よく考えたら、GraphQLサーバーはFirebase側で構築されるんだから、サーバーサイドのコードを一切書く必要ないのか…!
アプリケーションのデプロイ先は別にNodeサーバーじゃなくても静的に置いていいんだ
すげー

かがんかがん

https://firebase.google.com/docs/data-connect/web-sdk?hl=ja#using-queries

このドキュメントによれば listMoviesRef() とか listMovies() みたいにインスタンスわざわざ渡さなくても実行できるようなこと書いてあるけど、
やってみたら以下のようにdata connectのインスタンスを渡さないと、「initializeAppされていないぞエラー」が出てしまった。

const dataConnect = getDataConnect(app, connectorConfig);
const movies = await listMovies(dataConnect);

なにが違うんだろう 🤔

かがんかがん

GraphQLでしか書けないから、複雑な処理をしたくなったときにSQLを書くことはできないのか。
ここはもうこのサービスの特性として割り切るしかないかな。

かがんかがん

デプロイ

VSCode拡張の「Deploy to production」でデプロイできる
(もちろんcliコマンドでもOK)

デプロイすると、コンソールから確認できる

コンソールからクエリ・ミューテーションの実行もできる

画面の下の方に実行結果の履歴が出てくる

かがんかがん

コンソールからも、あくまでGraphQLを介してしか操作できなくって、テーブルのような表示はしてくれないのか…
それはちょっと不便かも。

かがんかがん

一応、CloudSQLのコンソール(Firebaseのコンソールではなく、Google Cloudの方のコンソール)に行けばSELECT文叩いて表示とかはできる。
(Data Connectの中身はCloudSQL)

かがんかがん

感想

Firestoreのようなお手軽さでRDB&GraphQLが使えるの素敵すぎる…!
Firestore (NoSQL) はどんなドキュメントでも入れられてしまうがゆえ、型安全な運用がなかなか難しかった。
小規模なプロジェクトであろうと、型に守られて実行時エラーを避けたいので、本当に嬉しい。

早くGAしてくれ~~

ログインするとコメントできます