複数のプロジェクトのfirebase-adminを起動して、開発用に本番データの一部を移行する
開発しているWebサービスで、本番データの一部を開発用に使いたいと思ったときの備忘録。
firebase-adminは複数のプロジェクトで使えるらしい。
開発用だけじゃなく、UIDを変更しながらのデータ移行などにも使えそう。
ローカル環境でfirebase-adminを使うための準備
準備の部分は、以前まとめたこちらを参照ください〜
- ローカルPCからfirebase-adminを使ってFirestoreを操作する(管理ツール) - くらげになりたい。
ソースはこんな感じ。
const admin = require("firebase-admin");
// *** 移行元のプロジェクトの設定
const srcSA = require("./key/XXXXX.json"); // サービスアカウントの秘密鍵を取得
// firebase-adminの初期化
admin.initializeApp({ credential: admin.credential.cert(srcSA) });
const srcDB = admin.firestore(); // firestoreのインスタンスを取得
// ** 移行先のプロジェクトの設定
const destSA = require("./key/XXXXX.json"); // サービスアカウントの秘密鍵を取得
// ※同じadminを使って、別のAppを作成しないといけない※
// ※2つ目を初期化する場合は、"dest"など名前をつけないといけない※
const destAdmin = admin.initializeApp( { credential: admin.credential.cert(destSA) }, "dest");
const destDB = destAdmin.firestore(); // firestoreのインスタンスを取得
// ****************************
// * MAIN
// ****************************
async function main() {
console.log(`***** START MAIN`);
// 移行元からデータを取得
const snaps = await srcDB.collection("data").get()
const srcData = snaps.docs;
for (let v of data) {
try {
// 移行先からデータを保存
const destDataRef = destDB.collection("data").doc(v.id);
await destDataRef.set(v.data());
} catch (error) {
console.errror(`Error: ${error}`, error);
}
}
console.log(`***** END MAIN`);
process.exit(0);
}
main().then();
雛形はこんな感じ。
以前書いた以下の記事だと丸々移行するので、UIDが変わるとめんどくさいことになる。。
この方法であれば、
- whereで一部のだけに絞り込んだり、
-
set()
するときに、UIDを差し替えたり
できるので、開発用に使うにはよいかんじ。
注意1: 2つ目を初期化する場合は別の名前に
そのまんまコピペで2つのfirebase-adminを作るとエラーに。。
2つ目を初期化する場合は、"dest"など名前をつけないといけないいけないらしい。。
公式ドキュメントの「複数のアプリを初期化する」に書いてあった。
これで、2つのfirebase-adminが起動できるので、データ移行などもできそう(´ω`)
注意2: メモリを大量に使いそうな場合はオプションを指定
データが多く、メモリを大量に使いそうな場合は、
--max_old_space_size
オプションを指定しないといけない。。
途中で失敗すると(読み込み/書き込み件数的に)悲しいことになるので、
大きめのサイズを指定しておくと良さそう。
node --max_old_space_size=8192 index.js
注意3: 件数が多い場合は、limitを指定して再帰処理
大量のデータを一度に取得しようとすると、
Deadline Exceeded error
が出て怒られるので、少しずつ実行するのがよいかんじ。
const BATCH_SIZE = 300
async function moveData(lastItem) {
// 移行元からデータを取得
const colRef = srcDB.collection("data");
let query = colRef.orderBy("createAt", "asc");
if (lastItem != null) query = query.startAfter(lastItem.createAt);
const snap = await query.limit(BATCH_SIZE).get();
if (snap.docs.length === 0) return; // 0件なら終了する
const srcData = snaps.docs;
for (let v of data) {
try {
// 移行先からデータを保存
const destDataRef = destDB.collection("data").doc(v.id);
await destDataRef.set(v.data());
} catch (error) {
console.errror(`Error: ${error}`, error);
}
}
// 最後の要素を渡して、そこから継続する
await moveData(data[data.length - 1]);
}
// ****************************
// * MAIN
// ****************************
async function main() {
console.log(`***** START MAIN`);
await moveData(null);
console.log(`***** END MAIN`);
process.exit(0);
}
注意4: 複数の場所に反映する場合は、batchやtransactionを使う
途中でエラーになる場合もあるので、batchやtransactionを使うとよさそう。
公式ドキュメントだと、このあたり
- トランザクションと一括書き込み | Firebase
for (let v of data) {
try {
const batch = destDB.batch();
// 移行先からデータを保存
const destDataRef = destDB.collection("data").doc(v.id);
batch.set(destDataRef, v.data());
// 移行先からデータを保存: その2
const destData2Ref = destDB.collection("data2").doc(v.id);
batch.set(destData2Ref, v.data());
// コミット
await batch.commit();
} catch (error) {
console.errror(`Error: ${error}`, error);
}
}
ループ外で使うほうのもいい感じ。
ただ、一括で書き込めるドキュメント数は500までと制限があるので、
一度に書き込む範囲は適宜調整が必要。
1 回のトランザクションまたは一括書き込みでは、
最大500のドキュメントに書き込みを行うことができます。
トランザクションと一括書き込み | Firebase
まとめ
firebase-adminは複数のプロジェクトでも扱える。
部分的なデータ移行や一部を書き換えながらの移行もできる(´ω`)
ただ、件数が多かったり、複数の書き込みがある場合は、いろいろ必要。。
こんなのつくってます!!
積読用の読書管理アプリ 『積読ハウマッチ』をリリースしました!
積読ハウマッチは、Nuxt.js+Firebaseで開発してます!
もしよかったら、遊んでみてくださいヽ(=´▽`=)ノ
要望・感想・アドバイスなどあれば、
公式アカウント(@MemoryLoverz)や開発者(@kira_puka)まで♪
Author And Source
この問題について(複数のプロジェクトのfirebase-adminを起動して、開発用に本番データの一部を移行する), 我々は、より多くの情報をここで見つけました https://qiita.com/kira_puka/items/e42d72d3a8b3e56597b9著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .