【Firebase】Firestore でバックアップを取る
はじめに
今回記事を初めて記事を投稿するので簡単に自己紹介します。株式会社キカガクという企業でソフトウェアエンジニアをしています。業務では主にReact/Nextを用いたフロントエンドの開発をしています。プロダクトの技術スタックがフロントエンドに寄せたものになっているので、バックエンドはFirebase(Cloud Functions)や GCPのcloud Runなどに持たせているフロントエンドドリブンな開発をしています。
今回はキカガクで日々フル活用している(しきれてはいない)Firestoreのバックアップについてまとめてみました。
なぜバックアップが必要なのか
データベースのバックアップはいはずもがな必要なのですが、そのバックアップのユースケースは思いつく限り、下記3つほどあると思います。もちろん他にもあると思いますので、ぜひぜひコメントで教えてください。
・Firestore で誤ってコレクション(データ)を削除してしまった場合
起きてはいけないことナンバー1ですが、万が一起きてしまってもバックアップをとっていればすぐに復旧できます。普通は開発環境でプロジェクトを立てて開発をしたり、Firestoreの通信はエミュレータを使用して本番環境のデータベースに影響を及ぼさないようにしているかと思います。
恥ずかしながら最近までエミュレータを知らず、実際に使用してみてとってもカンタンだったので、また後日記事にしてみようと思います。
・Firestore のスキーマを変更する場合
NoSQLのFirebaseにスキーマという言葉は若干違和感ありますが例えば、フィールドにマップ型で持たせていたデータをドキュメントにしたほうがいいと気づいた場合です。
/users/information/
userA: {name: 'hoge', age: 22, origin: 'Tokyo'},
userB: {name: 'fuga', age: 32, origin: 'Nagoya'},
...
こんな設計にはしないと思いますがあくまで一例です。笑
この場合、userAだけを取得したい場合でもdocument1
には行った他のユーザー情報もとってきてしまうので、無駄が多いです。
それ気づいた場合、とっておいたバックアップから
/users/userA/
name: 'hoge'
age: 22,
origin: 'Tokyo',
/users/userB/
name: 'fuga',
age: 32,
origin: 'Nagoya',
...
みたいに変更することができます。ここでは具体的なスキーマ変更方法は書きませんが、トランザクション処理をかませて行うことになるでしょうか。
・開発環境やステージング環境用にプロジェクトを複製する場合
本番環境との整合性をどうやって担保するかという話は一旦置いておいて、例えばテスト的にプロジェクトのデータを複製したい場合、バックアップ(移行)を行って開発を進めることができます。
当然移行するときに移行元のデータが消えてしまうことはないので、安心して開発できますね。
大まかな流れ
firebaseは比較的公式ドキュメントが充実しています。解説も割と詳しくしっかり書かれてあるので、公式ドキュメントをみながら進めていけると思います。
方法としては2つで、手動でバックアップを行う方法と定期実行を設定して自動で行う方法があります。
バックアップに必要な下準備
これらもすべてドキュメントに書かれていますが、念の為。
- blaze プラン(課金プラン)に加入していること
- 下記いづれかの権限が与えられていること
- Owner
- Cloud Datastore Owner
- Cloud Datastore Import Export Admin
- アクセス権の付与が必要な場合、Ownerに頼んで付与してもらうこと
バックアップ方法
- FirestoreA → StorageA (bucket の作成) → FirestoreB
- データ移行の場合、直接FirestoreA ⇆ FirestoreBでバックアップを行うのではなく、Storage を介して行う
サブコレクション以下のデータ移行について
当然ながらサブコレクションも移行する必要があると思います。その場合、
/collection1/{document}/collection2
のようにワイルドカードを駆使してパスを指定して書く必要はなく、ただ単純にコレクション名をコマンドに記載の通りに書くだけでOKです。
仮にサブコレクション名がルートのコレクションと重複している場合は二度書く必要はありません。
gcloud firestore export gs://[SOURCE_BUCKET] --collection-ids=collection1,collection2 --async
*1: scheduler の時間設定は unix-cron 形式(公式)
Discussion