3
2

More than 3 years have passed since last update.

FirestoreにJSON形式のデータをimportする(Subcollection込みで)

Last updated at Posted at 2020-05-19

概要

JSON形式のデータをFirestoreにimportしたい。
Subcollection込みで。

firestore-import-export

https://github.com/dalenguyen/firestore-import-export
いかにもな名前で期待感大ですが、
1. Firestoreでsubcollectionを含むcollectionを作成。
2. Firestoreからexportする(下記コマンド)と、JSONでエクスポートされる (出力ファイルをexport.jsonとする)
3. foo_collectionとbar_subcollectoinを削除する。
4. export.jsonをimportコマンド(下記参照)で取り込もうとするとsubcollectionがある場合はimportできない。orz

# exportコマンド
node export.js foo_collection bar_subcollection
# importコマンド
node import.js export.json

stackoverflow

賢い人っているんですねぇ。さらっと回答しています。
https://stackoverflow.com/questions/46640981/how-to-import-csv-or-json-to-firebase-cloud-firestore
General Solutionのセクション

コードを引用(Javascriptです)

const admin = require('../functions/node_modules/firebase-admin');
const serviceAccount = require("./service-key.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://<your-database-name>.firebaseio.com"
});

const data = require("./fakedb.json");

/**
 * Data is a collection if
 *  - it has a odd depth
 *  - contains only objects or contains no objects.
 */
function isCollection(data, path, depth) {
  if (
    typeof data != 'object' ||
    data == null ||
    data.length === 0 ||
    isEmpty(data)
  ) {
    return false;
  }

  for (const key in data) {
    if (typeof data[key] != 'object' || data[key] == null) {
      // If there is at least one non-object item in the data then it cannot be collection.
      return false;
    }
  }

  return true;
}

// Checks if object is empty.
function isEmpty(obj) {
  for(const key in obj) {
    if(obj.hasOwnProperty(key)) {
      return false;
    }
  }
  return true;
}

async function upload(data, path) {
  return await admin.firestore()
    .doc(path.join('/'))
    .set(data)
    .then(() => console.log(`Document ${path.join('/')} uploaded.`))
    .catch(() => console.error(`Could not write document ${path.join('/')}.`));
}

/**
 *
 */
async function resolve(data, path = []) {
  if (path.length > 0 && path.length % 2 == 0) {
    // Document's length of path is always even, however, one of keys can actually be a collection.

    // Copy an object.
    const documentData = Object.assign({}, data);

    for (const key in data) {
      // Resolve each collection and remove it from document data.
      if (isCollection(data[key], [...path, key])) {
        // Remove a collection from the document data.
        delete documentData[key];
        // Resolve a colleciton.
        resolve(data[key], [...path, key]);
      }
    }

読めばほぼ自明ですが、ちょっと補足。

importするライブラリ名

const admin = require('../functions/node_modules/firebase-admin');
// 設定によっては、↓かも
const admin = require('firebase-admin');

service account key

// GCPではいつもの、serive account keyの設定。
const serviceAccount = require("./service-key.json");

import対象のFirestoreの指定

 のところは、デフォルトだとプロジェクト名になっているはず。

  databaseURL: "https://<your-database-name>.firebaseio.com"

importするデータの指定

    // 読み込むJSON
    const data = require("./fakedb.json");

importするJSONの例

{
  "collection_name": {
    "document_identifier1" : {
      "field1": "hoge",
      "field2": 1,
      "array": ["element1","element2","element3"],
      "subcollection_name": {
        "document_identifier1_1": {
          "field3" : "foo",
          "field4" : 4
        },
        "document_identifier1_2": {
          "field3" : "foobar",
          "field4" : 5
        }
      }
    },
    "document_identifier2" : {
      "field1": "hogehoge",
      "field2": 2,
      "array": ["element4","element5","element6"],
      "subcollection_name": {
        "document_identifier2_1": {
          "field3" : "bar",
          "field4" : 6
        }
      }
    }
  }
}

document_identifierN は 何でもよいです。
Firestoreのデフォルトだと自動で生成されるランダムな20文字のものです。
→ 重複しなければ、 1 などにしても問題なしです。

あとがき

JSONやYAMLで取り込む機能は、公式が用意してしてくれてもいいのになぁ。

2020/11/08追記
良さそう
https://github.com/matsu0228/fsrpl
公式の実装はまだかなぁ。

3
2
1

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
3
2