答案 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
});
创建服务帐户密钥文件
我只是在App Engine默认服务帐户中添加了一个密钥
Create key函数将提供将密钥下载到JSON文件
JSON数据结构
要使用提供的脚本,数据结构必须如下:
{
"myCollection" : {
"UniqueKey1" : {
"field1" : "foo",
"field2" : "bar"
},{
"UniqueKey2" : {
"field1" : "fog",
"field2" : "buzz"
}...
}
答案 4 :(得分:5)
供参考。我编写了一个有助于在Firestore中导入和导出数据的函数。
答案 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)
如果集合的名称不仅由数字组成,则可以按以下方式定义文档的名称。
...
...
} 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代码的更改
答案 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和其他语言中可能会有类似的解决方法。