これは Firebase #2 Advent Calendar 2019の16日目の記事です. 昨日は、@H_Crane さんでした.
注意:2020/10追記
コマンドの破壊的変更がされたようです。
最新版でのコマンドは本記事ではなく、下記を参照してください
これは何
Firebaseの運用にとても便利な fsrpl (Firestore Replication Tool) と、その使い方について紹介します.
目的
Firebaseを運用していて、下記のニーズはよくあると思います。
- データ更新前に更新対象の特定のドキュメントだけをバックアップしておいて、万が一操作を間違えたらそのドキュメントだけを復元したい
- 特定のドキュメントを、別のCollection配下にコピーしたい
- 別のProjectのFirebaseから、他のFirebaseへ、特定のドキュメントのデータをコピーしたい
公式にCLIツールも提供されており一括バックアップ・一括復元などはできますが、特定のデータだけをバックアップし手軽に復元することはできないので、運用しにくいと感じていました。本記事では、上記ニーズを満たすCLIツールfsrpl
について紹介します。
Firebaseには、 Cloud Firestore
(以降Firestoreと呼ぶ) と RealtimeDatabase
の2種類のデータベースがありますが、現時点で fsrpl
が対応しているのは Firestore
のみのようです。
事前設定
インストール
- Macの場合は、homebrewで簡単にインストールできました
# homebrewを使ったインストール
# https://github.com/matsu0228/fsrpl#homebrew
brew tap matsu0228/homebrew-fsrpl
brew install fsrpl
fsrpl --help
- Go経由: fsrplは、Goで実装されているようで、Goがセットアップ済の環境であれば簡単にインストールできるようです
go get github.com/matsu0228/fsrpl
- バイナリからインストールする場合は、ここからダウンロードできるようです (LinuxもWindowsも対応していそうです)
Firebaseの認証鍵の用意
- Firebaseの認証鍵ファイルを公式ドキュメント のとおり取得して、任意のディレクトリに格納してください
使い方
必須オプション
処理対象のFirebaseの秘密鍵と、対象のパス(Collection + documentId)
- Firebaseの秘密鍵の指定方法は、2種類あります
-
--secret=
オプションで指定する.環境変数よりもこちらが優先されます. - 環境変数
FIRESTORE_SECRET
として指定する
-
- 対象のパス指定
- 引数として指定します。例:
users/tarou
のように、collectionId + documentId で指定してください(必ず偶数となります。)
- 引数として指定します。例:
利用例: firestoreのデータをローカル保存
- ローカルにバックアップするときには、
-f
オプションでディレクトリを指定します - 1documentに対して1ファイルを生成し、documentIdがファイル名として出力されます
$ fsrpl --secret=(your secret JSON) "users/taro" -f ./backups
$ ls ./backups
taro.json
- 特定のコレクション配下を指定する場合は、documemtIdの指定の代わりにワイルドカード(
*
)を指定すると、すべてのドキュメントを保存できます
$ fsrpl --secret=(your secret JSON) "users/*" -f ./backups
$ ls ./backups
taro.json jiro.json ......
利用例: ローカルにあるJSONファイルからfirestoreへ復元
- ローカルにバックアップ済のJSONファイルを、firestoreにインポートする場合は、
-i
オプションを利用します.
$ fsrpl --secret=(your secret JSON) "users/taro" -i ./backups/taro.json
# DocumentIdを指定してインポート
$ fsrpl --secret=(your secret JSON) "groups/A/users/usera" -i ./backups/taro.json
- また、
*
で一括インポートできます。このとき、ファイル名をdocumentIdとしてインポートするので、注意してください。既存のdocumentがあれば上書き更新します
$ fsrpl --secret=(your secret JSON) "users/*" -i ./backups/*.json
利用例: 特定のドキュメントを、別のCollection配下にコピー
Firebaseでは、破壊的なスキーマ変更をする場合は、既存データはそのままにして、コレクション名を変更した先に新しいスキーマでデータをいれていくといった運用をすると思います。そのときなどに、本利用例が役立ちます。
- 下記のようにして、
--destPath
を指定することで、別のCollectionへコピーできます.
$ fsrpl --secret=(your secret JSON) "users/taro" --destPath="groups/A/users/taro"
-
*
で、一括コピーもできます.このとき、DocumentIdは変えずにコピーします.
$ fsrpl --secret=(your secret JSON) "users/*" --destPath="usersData/*"
- コピーしたら元のドキュメントを削除したい場合は、
--delete
オプションで実現できます.
# users/* のドキュメントはすべて削除されます.サブコレクションは削除されません
$ fsrpl --secret=(your secret JSON) "users/*" --destPath="usersData/*" --delete
利用例: あるProjectのFirestoreから他のProjectのFirestoreへデータをコピー
Firestoreのprojectを変更をしたい 、開発用Firestoreから個人開発用のFirestoreにデータをコピーしたい、といったときに利用できます.1
- 別のfirestoreへのコピーを宣言するオプション
--destfs
と、そのfirestoreの認証鍵を指定するオプション--dest-secret
で実現できます.
# 1件だけコピー
$ fsrpl --secret=(your secret JSON) "users/taro" --destPath="users/*"
--destfs --dest-secret=(your another secret JSON) --destPath="users/taro"
# `*` で一括コピー
$ fsrpl --secret=(your secret JSON) "users/*" --destPath="users/*"
--destfs --dest-secret=(your another secret JSON) --destPath="users/*"
足りないところ
基本的にはとても便利に利用しているツールなのですが、もう少し改善するといいと思う点を書いてみます.
利用できるデータ型に制限がある
fsrpl
は現時点でβ版のツールのようです。 制限の項目に注意してご利用されることをお勧めます.
具体的には、「参照」や「地理座標」が入っているドキュメントは、このツールではコピーできないのでご注意ください.
再帰的にコピーができない
再帰的にコピーができると、もっと運用が楽になると思います.
具体的には、Firestoreではサブコレクションが利用でき下記のようにデータが保存するといったことがあります.下記の例では stockNoteList
がサブコレクション・ {noteId} / noteTitle
がその配下のドキュメントとなります.
# ユーザーごとにストックした記事データが保存されている
/users/ taro / stockNoteList / {noteId} / noteTitle
/ {noteId} / noteTitle
jiro / stockNoteList / {noteId} / noteTitle
/ {noteId} / noteTitle
fsrplでは、「ドキュメントの一括コピー」はできますが、サブコレクションごとコピーすることはできません
.
fsrpl --secret=(your secret JSON) "users/*" --destPath="usersData/*"
# 全ユーザーのドキュメントデータはコピーできるが、サブコレクション`stockNoteList`配下はコピーできない
/userData / taro / {documentData}
jiro / {documentData}
自分はshellで頑張って利用していますが、CLIツールの機能として提供してもらいたいです
fsrpl --secret=(your secret JSON) "users/*" --destPath="usersData/*"
userIds=("taro" "jiro")
for userId in ${userIds[@]} ; do
echo "copy stockNote of ${userId}"
fsrpl --secret=(your secret JSON) "users/${userId}/stockNoteList/*" --destPath="usersData/${userId}/stockNoteList/*"
done
オプションが多くて分かりづらい
実現したいことごとにオプションを指定する必要があるのでしょうがない点もありますが、オプションが多いので毎回しらべてから利用する手間を感じます.
たとえば、TUIクライアントとしての機能があれば、 fsrpl
を実行すると、「対象のコレクションを指定してください」のようなウィンドウを表示させて、グラフィカルに操作することもできるかなと思います.
参考:@gorilla0513 さんの docui を知り、TUIクライアントとしてこんなに直感的に操作できるツールがあることに驚きました
最後に
みなさんは、Firebase運用にあたって、どのような工夫をされていますか??
なにかノウハウがあれば、コメントいただきたいです!!
明日は、 @masashi-sutou さんです。お楽しみに!
-
話題のアドベントカレンダーでも GCP Projectを消しちゃった話 として言及がありましたが、Firebaseを消すとGCPのプロジェクトも全て消えるので注意してください. ↩