はじめに
Firestoreの読み取りコストを削減するための仕組みとして、Firestore Data Bundlesがあります。
基本的にはクライアントのSDK(Webやモバイル)からの利用が想定されていますが、サーバーサイドからも利用することはできないか調査しました。
結論
- Firestore Data Bundlesはただの静的ファイルなのでサーバーサイドからも読み取ることは可能
- ただしマッチョな実装になるので少々注意が必要
Firestore Data Bundlesとは
公式ドキュメントもありますが、上記ブログ記事がとても分かりやすいです。
コードと内容ともかなり参考にさせていただきました。
簡単にまとめると、Firestore Data BundlesとはFirestore上の読み取り頻度が高いデータを静的ファイル化しCDN、ホスティング サービス、その他に展開して利用する仕組みです。
クライアントはFirestoreを呼び出さなくてもデータにアクセスできるため、アクセスコストの削減やクエリ結果の高速な読み込みが期待できます。
下記のような流れで処理が進むイメージです。
1. サーバーサイド: Firestoreデータ読み取り
↓
2. サーバーサイド: Bundles形式に変換
↓
3. サーバーサイド: 静的ファイル化 ex. txtファイル
↓
4. サーバーサイド: CDN、ホスティング サービス、その他にアップロード
↓
5. クライアント: 静的ファイルを取得
↓
6. クライアント: Bundles形式として読み込み
②の「Bundles形式に変換」についてはNode.jsやJava、PythonのAdmin SDKが対応しています。
// Build the bundle
// Note how querySnapshot is named "latest-stories-query"
var bundleBuffer = bundle.add(docSnapshot); // Add a document
.add('latest-stories-query', querySnapshot) // Add a named query.
.build()
⑥の「Bundles形式として読み込み」についてはWebやモバイルのSDKが対応しています。
await db.loadBundle(resp.body);
Firestore Data Bundles形式のデータは、Firestoreドキュメントの内容と、それらを生成したクエリに関するメタデータの両方が含まれたJSONのような形式です(下記のスクショ。一部黒塗り)。
サーバーサイドで利用する試み
前述の通り、Firsetore Data Bundlesを読み込んで利用するためのAPI(ex. loadBundle()
)はWebやモバイルのSDKにしか用意されていません。
しかし、Firestore Data Bundlesはただの静的ファイル(先ほどのスクショの場合はテキストファイル)なので、SDKを利用せずともサーバーサイドでも読み込むことはできそうです。
中身はほぼjsonですが余分な数字が入ってるのと、複数のjsonオブジェクトがちゃんと連結されてないので配列可しました。
上記ブログ記事に記載の通り、Firestore Data Bundlesは余分な数字が入ったJSONといった面持ちで絶妙に取り回しづらくなってはいますが、正規表現等々用いてキレイにしてあげます。
var (
headNumber = regexp.MustCompile("^[0-9]{3}{")
middleNumber = regexp.MustCompile("}[0-9]{3}{")
)
func replaceHeadNumber(str string) string {
return headNumber.ReplaceAllString(str, "[{")
}
func replaceMiddleNumber(str string) string {
return middleNumber.ReplaceAllString(str, "},{")
}
func bundlesToJSONString(str string) string {
str = replaceHeadNumber(str)
return replaceMiddleNumber(str) + "]"
}
func bundlesToJSON(str string) ([]any, error) {
var ret []any
formatted := bundlesToJSONString(str)
if err := json.Unmarshal([]byte(formatted), &ret); err != nil {
return nil, err
}
return ret, nil
}
このようにすれば、サーバーサイドでもFirestore Data Bundlesに含まれるドキュメントにアクセスすることができます。
ただし、あくまでテキストファイルを無理やり読み込んでいるだけなので、例えばFirebase Data Bundlesのデータ仕様が変更になった際には、動かなくなる可能性があります。
フルのコードはこちらに置いています。
終わりに
- Firestore Data Bundlesをサーバーサイドからも利用することができるか調査しました
- 結論として、利用は可能ですが、仕様変更にロバストではなく実戦投入には課題が残ります
- サーバーサイドでFirestoreのコスト削減に挑む場合の方法については今後も模索していきたいです