LoginSignup
29

More than 3 years have passed since last update.

Firestoreの運用が捗るデータ移行ツールfsrpl

Last updated at Posted at 2019-12-15

これは 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 さんです。お楽しみに!


  1. 話題のアドベントカレンダーでも GCP Projectを消しちゃった話 として言及がありましたが、Firebaseを消すとGCPのプロジェクトも全て消えるので注意してください. 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29