初めに
Firestoreでアプリを開発していく中で文字列だったデータを配列に変更したい場面があり
データが沢山あり、一つ一つ変更するのが大変だと思いfirebase-adminを使おうと思いました。
それと、変更してもしアプリが動作しなくなっても大丈夫なようにfirestore-export-importも
一緒に使用しようと作成したものを紹介します。
おまけで「firestore-export-importでバックアップおよび復元する方法」も一緒にご紹介します。
参考
前提
- node v16.15.0
- npm v8.5.5
- firebase-admin v11.0.0
- firestore-export-import v1.2.0
- yarn v1.22.18
Firestoreのフィールドを変更、追加する時の手順
- nodeプロジェクトを作成する
- Firebaseの鍵を取得する
- 現在のFirestoreのBackUp(export)する
・tools/backup.ts
- Firestoreのドキュメントにフィールドを一括で変更、追加する
・firebase-batch/index.ts
- データ変更、追加がうまくいかなったら、BackUp(export)していたデータをimportして復元する
・tools/restore.ts
//ファイル構成
firebase-app/
├─ key/
│ └─ ダウンロードしたjsonファイル
├─ firebase-batch/
│ └─ index.ts
└─ tools/
├─backup.ts
└─restore.ts
1. nodeプロジェクトを作成する
- firebaseフォルダを作成(フォルダ名は任意)
$ mkdir firebase-app
- firebase-appフォルダに移動
$ cd firebase-app
- npmを初期化
$ yarn init
- firebase-adminパッケージを追加
$ yarn add firebase-admin
- firestore-export-importをインストールします。
npm install firestore-export-import
oryarn add firestore-export-import
2. Firebaseの鍵を取得
Firebase Admin SDKでFirestoreにアクセスするため、サービスアカウントの .json秘密鍵が必要
新しい秘密鍵の生成からjsonファイルをダウンロードする
3.firestore-export-importを使ってFirestoreのBackUpをする
const { initializeFirebaseApp } = require('firestore-export-import');
const serviceAccount = require('../key/先ほどダウンロードしたjsonファイル');
const appName = '[DEFAULT]';
initializeFirebaseApp(serviceAccount, appName);
const fs = require('fs');
const { backup } = require('firestore-export-import');
backup('users')
.then((collections) => {
const json = JSON.stringify(collections);
fs.writeFile('collection-users-backup.json', json, 'utf8',()=>{
//collection-users-backup.jsonという名前のファイルにusersコレクションのデータが入ります。
console.log('done');
console.log(JSON.stringify(collections));
});
});
ここまで出来たら、実行すればusersコレクションのデータが入ったjsonファイルが作成されます。
実行コマンド$ node tools/backup.ts
ファイル名は任意です。
4. Firestoreのドキュメントにフィールドを一括で変更、追加する
-
firebase-appフォルダの直下にkeyフォルダを作成し、秘密鍵で取得したjsonファイルを追加する。
-
firebase-appフォルダの直下にfirebase-batchフォルダを作成し、firebase-batchフォルダの直下に下記のファイルを追加する。
const { initializeApp,cert } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore');
const serviceAccount = require('../key/先ほどダウンロードしたjsonファイル');
(async () => {
try {
initializeApp({
credential: cert(serviceAccount),
});
const db = getFirestore();
const querySnapshot = await db.collection('users').get();
const batch = db.batch();
querySnapshot.forEach((postDoc) => {
batch.set(
//firestoreの[usersコレクション]のadminの値を全て「true」に変更、追加したい時は以下のようにする
db.collection('users').doc(postDoc.id),
{
//変更、追加したいデータを書く
admin: true,
},
{ merge: true }
);
console.log(postDoc.data().displayName);
});
await batch.commit();
} catch (err) {
console.log(Error: ${JSON.stringify(err)}
);
console.log(err);
}
})();
:::note warn
注意
既存のデータを上書きしないようにするには, merge をtrueに指定する必要があります
ここを指定しないと他の属性が消され、上書きされてしまいます。
:::
ここまで出来たら、実行すればusersコレクションのadminの値をtrueに一括変更、追加出来ます。
実行コマンド$ node firebase-batch/index.ts
5. firestore-export-importを使ってFirestoreをimportをする
const { initializeFirebaseApp, restore } = require('firestore-export-import');
const serviceAccount = require('../key/先ほどダウンロードしたjsonファイル');
const appName = '[DEFAULT]'
initializeFirebaseApp(serviceAccount, appName)
//Backup(export)したファイル
restore('collection-users-backup.json', {
autoParseDates: true,// timestamp → Date変換
});
ここまで出来たら、実行すればBackup(export)したデータがFirestoreに入ります。
実行コマンド$ node tools/restore.ts
:::note warn
注意
autoParseDatesをtrueにしないと
そのままFirestoreに{seconds: 161720761, nanoseconds: 51000000}とデータが入ります。
:::