Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cloud Firestore With Go

mtskhs
April 24, 2021

Cloud Firestore With Go

GoConference2021Spring LTでの発表資料です。

* そもそもCloud Firestoreって
* Cloud FirestoreのGoによる開発爆速入門
* Cloud Firestoreの運用ツール開発における知見

mtskhs

April 24, 2021
Tweet

More Decks by mtskhs

Other Decks in Programming

Transcript

  1. Who am I 2 •  @mtskhs • Go / React

    Native / TypeScript • Go Conference 2019 Autumn Goにおける API Client実装パターン https://speakerdeck.com/matsu0228/api-client-implementation-pattern-in-go • fsrpl - Cloud Firestoreの運用ツール https://firebaseopensource.com/projects/matsu0228/fsrpl/
  2. Contents 1. Cloud Firestore With Go 1.1. About Cloud Firestore

    1.2. When to use Go SDK 1.3. How to use Go SDK 1.4. Credentials on GCP 2. fsrpl - Firestore replication tool written by Go 2.1. about fsrpl 2.2. Key points for OSS development 4
  3. 1-1. About Cloud Firestore 6 👍👍 Pros • clientから直接接続できる(そのためのセキュリティールール) •

    リアルタイム更新     ※⚠GoのSDKではサポート外 • スケーラビリティ • NoSQL / 柔軟なスキーマ変更が可能 • 低価格 • トランザクション・整合性
  4. 1-1. About Cloud Firestore 7 😦😦 Cons • 検索が苦手 ◦

    Like句のサポートなし ◦ Where句やOrder句に指定したフィールドを持たないドキュメント は検索ヒットしない(ゼロ埋めが必要) ◦ Where IN句のサポートがあるが、10件以下しか指定できない ◦ 複数のWhere条件を指定するにはindex追加が必要 • 総じて、設計を工夫しないとデータ取得に時間がかかる ◦ ↑CQRS(コマンドクエリ責務分離。書き込みと読み込みのモデルを 分ける)の活用など、工夫は可能
  5. 1-2. When to use Firestore Go 8 前述のとおり、 • Firestoreには、Clientから直接参照・書き込みすることができる

    • GoのSDKではサポート対象外機能もいくつかある(リアルタイム更新 ・BulkWriterなど) 使い所(だと個人的に感じるの)は、 • 外部からのデータを タイムラグをできるだけ少なくしてFirestoreに保 存する場合 • Firestore Triggerが使えるCloud Functionsを使う際、限られたリソー ス(メモリ/最大処理時間9min)で重い処理を扱う場合 etc • Goが書きたいとき😌
  6. 1-3. How to use Go SDK 9 • Read -

    Get dsnap, err := client.Collection("cities").Doc("BJ").Get(ctx) if err != nil { return nil, err } var c City dsnap.DataTo(&c) // 👈構造体に fmt.Printf("Document data: %#v\n", c) https://firebase.google.com/docs/firestore/query-data/get-data#custom_objects
  7. 1-3. How to use Go SDK 10 • Read -

    Query iter := client.Collection("cities").Where("capital", "==", true) .Documents(ctx) // 👈 "==" がクエリ演算子。次の値と等しいとき for { doc, err := iter. Next() if err == iterator.Done { break } if err != nil { return err } fmt.Println(doc.Data()) } https://firebase.google.com/docs/firestore/query-data/get-data#get_multiple_documents_from_a_collecti
  8. 1-3. How to use Go SDK 11 • Read -

    Query operators https://firebase.google.com/docs/firestore/query-data/queries#query_operators • < 次の値未満 • <= 次の値以下 • == 次に等しい • > 次の値より大きい • >= 次の値以上 • != 次と等しくない • array-contains 配列要素を含む • array-contains-any いずれかに一致する配列要素を含む。最大 10件まで • In / not-in いずれかに一致する/しない。最大10件まで
  9. 1-3. How to use Go SDK 12 • Write -

    insert or update all fields _, err := client.Collection("cities").Doc("LA").Set(ctx, map[string]interface{}{ "name": "Los Angeles", "state": "CA", "country": "USA", })// 👈データ型は、struct tag付きの構造体でもよい if err != nil { return err } https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_docume
  10. 1-3. How to use Go SDK 13 • Write -

    insert or update partial fields _, err := client.Collection("cities").Doc("BJ").Set(ctx, map[string]interface{}{ "capital": true, }, firestore.MergeAll) // 👈Setの第二引数にMergeAllする if err != nil { return err } https://firebase.google.com/docs/firestore/manage-data/add-data#update-da
  11. 1-3. How to use Go SDK 14 • Write -

    delete _, err := client.Collection("cities").Doc("DC").Delete(ctx) if err != nil { return err } https://firebase.google.com/docs/firestore/manage-data/delete-data#delete_documen
  12. 1-3. How to use Go SDK 15 • Transaction ref

    := client.Collection("cities").Doc("SF") err := client. RunTransaction (ctx, func(ctx context. Context, tx *firestore. Transaction) error { doc, err := tx. Get(ref) // tx.Get, NOT ref.Get! if err != nil { return err } pop, err := doc. DataAt("population") if err != nil { return err } // 👇更新処理中(tx.Set)に同時編集が影響する場合は、トランザクション関数が複数回実行される return tx.Set(ref, map[string]interface{}{ "population": pop.(int64) + 1,}, firestore.MergeAll) }) if err != nil { return err } https://firebase.google.com/docs/firestore/manage-data/transactions#transaction
  13. 1-4. Credentials on GCP 16 • GCP上で認証・初期化する import ( firebase

    "firebase.google.com/go" "google.golang.org/api/option" ) // ... ctx := context. Background() conf := &firebase. Config{ProjectID: projectID} // projectIDを指定するだけでよい app, err := firebase. NewApp(ctx, conf) if err != nil { return err } client, err := app. Firestore(ctx) if err != nil { return err } defer client.Close() https://firebase.google.com/docs/firestore/quickstart#initialize
  14. 1-4. Credentials on GCP 17 • GCP以外で認証する - サービスアカウントの秘密鍵を環境変数指定 //

    環境変数GOOGLE_APPLICATION_CREDENTIALS を設定して実行する // export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account.json" import ( firebase "firebase.google.com/go" ) // ... ctx := context. Background() app, err := firebase. NewApp(ctx, nil) // optionは指定しないでよい if err != nil { return err } client, err := app. Firestore(ctx) if err != nil { return err } defer client.Close() https://firebase.google.com/docs/admin/setup#initialize-sdk
  15. Contents 1. Cloud Firestore With Go 1.1. About Cloud Firestore

    1.2. When to use Go SDK 1.3. How to use Go SDK 1.4. Credentials on GCP 2. fsrpl - Firestore replication tool written by Go 2.1. about fsrpl 2.2. Key points for OSS development 18
  16. 2-1. About fsrpl 19 • Firestoreの運用における辛みを解決できるツール ◦ copy - 指定したドキュメントを、別のパスにコピー

    ◦ copy - 指定したFirestoreから、別のFirestoreへコピー ◦ dump - 指定したドキュメントを、ローカルにjsonファイルとしてダン プ ◦ restore - ローカルのjsonファイルを指定したパスにリストア https://firebaseopensource.com/projects/matsu0228/fsrpl/
  17. 2-2. Key points for OSS development 20 • サービス開発を通して生じた辛みを解決できるものを💪 ◦

    自サービスの特定ユースケースに閉じずに一般化 • IFを意識🔧 既存の類似ライブラリ(mysqldump)と同様に • 機会を探した - Firebase Open Source https://firebaseopensource.com
  18. Summary 1. Cloud FirestoreをGoで扱う方法 • そもそもFirestoreって • 簡単なCRUD • 環境に応じたFirestoreの初期化方法

    2. Fsrpl - Firestore運用ツールの紹介 • copy, dump, restore • OSS開発における知見 21