【发布时间】:2018-03-20 08:10:11
【问题描述】:
【问题讨论】:
-
查看我的帖子以获得一般解决方案,也可以处理子集合。
标签: firebase google-cloud-firestore
【问题讨论】:
标签: firebase google-cloud-firestore
没有,此时您需要编写自己的脚本。
【讨论】:
到目前为止,您不能……firestore 将数据构造成不同的格式,即使用集合,每个集合都有一系列文档,然后以 JSON 格式存储……将来他们可能会成为一个工具将 JSON 转换为 firestore.. 以供参考,请查看
:https://cloud.google.com/firestore/docs/concepts/structure-data
****编辑:****
您可以在一定程度上自动化该过程,即编写一个模拟软件,仅将 CSV 或 JSON 数据的字段推送到 Cloud Firestore 数据库中。我迁移了整个数据库,只制作了一个简单的应用程序,该应用程序检索了我的数据库并将其推送到 Firestore
【讨论】:
https://gist.github.com/JoeRoddy/1c706b77ca676bfc0983880f6e9aa8c8
这应该适用于对象的对象(通常设置了多少旧的 firebase json)。您可以将该代码添加到已配置 Firestore 的应用中。
只要确保它指向正确的 JSON 文件即可。
祝你好运!
【讨论】:
您需要一个自定义脚本来执行此操作。
我基于 Firebase admin 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
【讨论】:
一般解决方案
我发现许多脚本允许上传 JSON,但没有一个允许子集合。我上面的脚本处理任何级别的嵌套和子集合。它还处理文档有自己的数据和子集合的情况。这是基于集合是对象的数组/对象(包括空对象或数组)的假设。
要运行脚本,请确保您已安装 npm 和 node。然后以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);
【讨论】:
供参考。我写了一个函数来帮助在 Firestore 中导入和导出数据。
【讨论】:
我使用了 Maciej Caputa 提供的通用解决方案。谢谢(:
这里有一些提示。假设您在该解决方案的 functions 文件夹中安装了 Ionic Firebase 应用程序,其中包含所需的 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
});
创建服务帐户密钥文件
我只是为 App Engine 默认服务帐户添加了一个密钥
创建密钥功能将提供将密钥下载到 JSON 文件的功能
JSON 数据结构
要使用提供的脚本,数据结构必须如下:
{
"myCollection" : {
"UniqueKey1" : {
"field1" : "foo",
"field2" : "bar"
},{
"UniqueKey2" : {
"field1" : "fog",
"field2" : "buzz"
}...
}
【讨论】:
这是一个小的修改,将文档的“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);
【讨论】:
如果您的集合的名称不仅由数字组成,那么您可以如下定义文档的名称。
...
...
} 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]);
}
}
}
同上例,子集合的名称不能只包含数字。
...
...
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 代码的更改
【讨论】:
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');
});
【讨论】:
Python 中的这种解决方法可能对某些人有所帮助。首先使用 Pandas 将 json 或 csv 转换为 dataframe,然后将 dataframe 转换为字典并将字典上传到 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 和其他语言中可能存在类似的解决方法。
【讨论】: