🐡

firestoreからjsonファイルにexportする

2022/05/17に公開

概要

  • Firestoreのデータをjson形式でexportする

背景

  • Firestoreのバックアップは有料で、GCPのバケットにバックアップを行えるが個人開発だとなるべく無料でいきたいですよね!?(圧)

前提

  • node v16.13.2
  • npm 8.10.0
  • "firebase-admin": "^10.2.0"
  • yarn 1.22.11

GCPを使えば有料でExport/Importが提供されているらしい

nodeプロジェクトを作成する

  • firebaseフォルダを作成
    • mkdir firebase
    • フォルダ名は任意
  • firebaseフォルダに移動
    • cd firebase
  • npmを初期化
    • yarn init
  • firebase-adminパッケージを追加
    • yarn add firebase-admin

Firebaseのサービスアカウントを作成し、鍵を取得

  • Firebase Admin SDKでFirestoreにアクセスするため、サービスアカウントの .json秘密鍵が必要
    • 新しい秘密鍵の生成からjsonファイルをダウンロードする

やっていること

  • firebase-admin初期化
  • サービスアカウントの秘密鍵(jsonファイル)を取得
  • ドキュメントのスナップショットを取得
  • ドキュメントデータに変換
  • ドキュメントデータをJSON Stringに変換
  • jsonファイルに書き出し

注意点

  • Timestamp 型は以下のように、_seconds_nanosecondsに分離されます
"createdAt": {
    "_seconds": 1649745738,
    "_nanoseconds": 968000000
    }

全文

  • コレクション名は適宜変えてください
    • 例:recipes
  • 以下のスクリプトを回すと、同じ階層にoutput.jsonが作成されます。
    • 適宜、ファイル名も任意のものに変えてください
const fs = require("fs");
const {
  initializeApp,
  cert,
} = require("firebase-admin/app");
const {
  getFirestore,
} = require("firebase-admin/firestore");

const serviceAccount = require("先ほどダウンロードしたjsonファイルのパス");

(async () => {
  try {
    initializeApp({
      credential: cert(serviceAccount),
    });
    const db = getFirestore();

    const querySnapshot = await db.collection("recipes").get();

    const docs = querySnapshot.docs.map((doc) => doc.data());
    const jsonContent = JSON.stringify(docs);
    fs.writeFile("output.json", jsonContent, "utf8", function (err) {
      if (err) {
        console.log("An error occured while writing JSON Object to File.");
        return console.log(err);
      }

      console.log("JSON file has been saved.");
    });

    await batch.commit();
  } catch (err) {
    console.log(`Error: ${JSON.stringify(err)}`);
  }
})();

作成されたjsonファイル

  • 一部URLのパスは変更しています。
[
    {
        "tips": "調味料はお好みで調整してください。",
        "refrigerationPeriod": {
            "value": "4",
            "unit": "日"
        },
        "freezingPeriod": {
            "unit": "不可",
            "value": "0"
        },
        "numberPersons": "2",
        "processes": [
            {
                "image": {
                    "name": "A0D2FCAE-2C99-4A0C-B11E-5CE56608B2D220220324102706.jpeg",
                    "createdAt": {
                        "_seconds": 1648128426,
                        "_nanoseconds": 726000000
                    },
                    "imgPath": "https://example.com",
                    "mimeType": "image/jpeg"
                },
                "description": "ブロッコリーはよく洗い、小房に分けます。耐熱ボウルに入れ、大さじ2の水をかけラップをし、600Wの電子レンジで3〜4分加熱します。"
            },
            {
                "image": {
                    "createdAt": {
                        "_seconds": 1648128436,
                        "_nanoseconds": 613000000
                    },
                    "name": "79A36639-A7FF-463C-9DB5-28A369BC56BF20220324102716.jpeg",
                    "imgPath": "https://example.com",
                    "mimeType": "image/jpeg"
                },
                "description": "あら熱が取れたら、カニカマをほぐしいれ、(A)を入れてよく混ぜ合わせたら、完成です。"
            }
        ],
        "isDeleted": false,
        "updatedAt": {
            "_seconds": 1648385004,
            "_nanoseconds": 129000000
        },
        "deletedAt": {
            "_seconds": 1648385004,
            "_nanoseconds": 129000000
        },
        "recipeTitle": "ブロッコリーとカニカマのサラダ",
        "createdAt": {
            "_seconds": 1648128469,
            "_nanoseconds": 82000000
        },
        "thumbnailImg": {
            "name": "F8DBDA0A-03B6-4BFD-90DF-7CED729D54A120220327094319.jpeg",
            "mimeType": "image/jpeg",
            "createdAt": {
                "_seconds": 1648384999,
                "_nanoseconds": 263000000
            },
            "imgPath": "https://example.com"
        },
        "ingredients": [
            {
                "amount": "200",
                "name": "ブロッコリー"
            },
            {
                "name": "カニカマ",
                "amount": "4本"
            },
            {
                "name": "(A)醤油",
                "amount": "小さじ1"
            },
            {
                "amount": "小さじ1",
                "name": "(A)酢"
            },
            {
                "name": "(A)マヨネーズ",
                "amount": "大さじ2"
            },
            {
                "name": "(A)白いりごま",
                "amount": "適量"
            }
        ]
    },
    {
        "thumbnailImg": {
            "mimeType": "image/jpeg",
            "name": "7AE425E1-EE9A-44EE-8D75-1A05E21B9BF320220412034218.jpeg",
            "imgPath": "https://example.com",
            "createdAt": {
                "_seconds": 1649745738,
                "_nanoseconds": 968000000
            }
        },
/// 以下略

最後に

Discussion