如何将CSV或JSON导入firebase云端防火墙

时间:2017-10-09 07:33:26

标签: firebase google-cloud-firestore

有没有办法像firebase实时数据库一样将CSV或JSON导入firebase云端防火墙?

enter image description here

11 个答案:

答案 0 :(得分:47)

常规解决方案

我发现许多内容允许上传JSON,但没有一个允许子集合。我上面的脚本处理任何级别的嵌套和子集合。它还处理文档具有自己的数据和子集合的情况。这是基于集合是对象的数组/对象(包括空对象或数组)的假设。

要运行脚本,请确保已安装npm和节点。然后将代码运行为node <name of the file>。请注意,无需将其部署为云功能。

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]);
      }
    }

    // If document is empty then it means it only consisted of collections.
    if (!isEmpty(documentData)) {
      // Upload a document free of collections.
      await upload(documentData, path);
    }
  } else {
    // Collection's length of is always odd.
    for (const key in data) {
      // Resolve each collection.
      await resolve(data[key], [...path, key]);
    }
  }
}

resolve(data);

答案 1 :(得分:16)

您需要一个自定义脚本来执行此操作。

我根据Firebase管理SDK编写了一个,只要firebase库不允许您导入嵌套数组数据。

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

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

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://YOUR_DB.firebaseio.com"
});

data && Object.keys(data).forEach(key => {
    const nestedContent = data[key];

    if (typeof nestedContent === "object") {
        Object.keys(nestedContent).forEach(docTitle => {
            admin.firestore()
                .collection(key)
                .doc(docTitle)
                .set(nestedContent[docTitle])
                .then((res) => {
                    console.log("Document successfully written!");
                })
                .catch((error) => {
                    console.error("Error writing document: ", error);
                });
        });
    }
});

更新:我写了一篇关于此主题的文章 - Filling Firestore with data

答案 2 :(得分:8)

没有,你现在需要编写自己的脚本。

答案 3 :(得分:6)

我使用了Maciej Caputa提供的通用解决方案。谢谢(:

以下是一些提示。假设您在该解决方案的functions文件夹中安装了所需的Firebase节点模块的Ionic Firebase应用程序。这是标准的Ionic Firebase安装。我创建了一个导入文件夹来保存同一级别的脚本和数据。

文件夹层次结构

myIonicApp
    functions
        node_modules
            firebase-admin
ImportFolder
    script.js
    FirebaseIonicTest-a1b2c3d4e5.json
    fileToImport.json

脚本参数

const admin = require('../myIonicApp/functions/node_modules/firebase-admin'); //path to firebase-admin module
const serviceAccount = require("./FirebaseTest-xxxxxxxxxx.json"); //service account key file

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://fir-test-xxxxxx.firebaseio.com" //Your domain from the hosting tab
});

Domain name from the Hosting tab

创建服务帐户密钥文件

  • 在项目的Firebase控制台中,在项目旁边 Overwiew项目,单击齿轮图标,然后选择用户和 权限
  • 在屏幕底部,单击“高级权限” 设置

Accessing Google Cloud Platform Console

  • 这将打开Goog​​le云端控制台的另一个标签
  • 在左侧选择服务帐户项
  • 为现有服务帐户创建服务帐户

我只是在App Engine默认服务帐户中添加了一个密钥

Create key函数将提供将密钥下载到JSON文件

Creating the Service Account Key

JSON数据结构

要使用提供的脚本,数据结构必须如下:

{
  "myCollection" : {
    "UniqueKey1" : {
      "field1" : "foo",
      "field2" : "bar"
    },{
    "UniqueKey2" : {
      "field1" : "fog",
      "field2" : "buzz"
    }...
}

答案 4 :(得分:5)

供参考。我编写了一个有助于在Firestore中导入和导出数据的函数。

https://github.com/dalenguyen/firestore-import-export

答案 5 :(得分:1)

目前还没有,你不能......将数据结构化为不同的格式,即使用集合,每个集合都有一系列文档,然后以JSON格式存储。将来他们可能会制作一个工具将JSON转换为firestore ..供参考检查

https://cloud.google.com/firestore/docs/concepts/structure-data

****编辑:****

您可以在某种程度上自动执行该过程,即编写一个模拟软件,该软件仅将CSV或JSON数据的字段推送到您的Cloud Firestore数据库中。我将我的整个数据库迁移到了一个简单的应用程序中,该应用程序检索了我的数据库并将其推送到Firestore

答案 6 :(得分:1)

https://gist.github.com/JoeRoddy/1c706b77ca676bfc0983880f6e9aa8c8

这适用于对象的对象(通常设置firebase json的大小)。您可以将该代码添加到已使用Firestore配置的应用程序。

确保将其指向正确的JSON文件。

祝你好运!

答案 7 :(得分:0)

这是一个小的修改,它将文档的“ id”(如果存在)复制到其路径。否则,它将使用“ for”的索引。

  ...
  ...
  } else {
    // Collection's length of is always odd.
    for (const key in data) {
      // Resolve each collection.
      if (data[key]['id']!==undefined)
        await resolve(data[key], [...path,data[key]['id']])
      else 
        await resolve(data[key], [...path, key]);
    }
  }
}

resolve(data);

答案 8 :(得分:0)

1-仅导入集合

如果集合的名称不仅由数字组成,则可以按以下方式定义文档的名称。


    ...
    ...

    } else {
        // Collection's length of is always odd.
        for (const key in data) {
          // // Resolve each collection.

          // If key is a number it means that it is not a collection
          // The variable id in this case will be the name of the document field or you 
          // can generate randomly
          let id = !isNaN(key) ? data[key].id : key;

          await resolve(data[key], [...path, id]);
        }
      }
    }

2-导入集合和子集合

与上面的示例相同,子集合的名称不能仅包含数字。

    ...
    ...

    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];

        // If key is a number it means that it is not a collection
        // The variable id in this case will be the name of the document field or you 
        // can generate randomly
        let id = !isNaN(key) ? data[key].id : key;

        // Resolve a colleciton.
        resolve(data[key], [...path, id]);
      }
    }

    ...
    ...
  

注意:@Maciej Caputa代码的更改

答案 9 :(得分:0)

var admin = require('firebase-admin');

var serviceAccount = require('./serviceAccountKey.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: 'https://csvread-d149c.firebaseio.com'
});

const csv = require('csv-parser');  
const fs = require('fs');

const firestore = admin.firestore();

// CSV FILE data.csv

// Name,Surname,Age,Gender
// John,Snow,26,M  
// Clair,White,33,F  
// Fancy,Brown,78,F

fs.createReadStream('data.csv')  
  .pipe(csv())
  .on('data', (row) => {
    console.log(row);
    if(row) {
      firestore.collection('csv').add({
        name: row.Name,
        surname: row.Surname,
        age: row.Age,
        sex: row.Gender
      });
    }
    else {
      console.log('No data')
    }
  })
  .on('end', () => {
    console.log('CSV file successfully processed');
  });

答案 10 :(得分:0)

此Python解决方法可能会对某些人有所帮助。首先使用Pandas将json或csv转换为数据帧,然后将数据帧转换为字典并将字典上载到firestore。

import firebase_admin as fb
from firebase_admin import firestore
import pandas as pd

cred = fb.credentials.Certificate('my_credentials_certificate.json')
default_app = fb.initialize_app(cred)
db = firestore.client()

df = pd.read_csv('data.csv')
dict = df.to_dict(orient='records')

my_doc_ref = db.collection('my_collection').document('my_document')
my_doc_ref.set(dict)

使用与Pandas类似的库,在javascript和其他语言中可能会有类似的解决方法。