Existe-t-il un moyen d'importer du CSV ou du JSON dans Fireestore FireBase Cloud, comme dans une base de données temps réel FireBase?
Solution générale
J'ai trouvé de nombreuses possibilités dans un script permettant de télécharger un JSON, mais aucune d'entre elles n'autorisait de sous-collections. Mon script ci-dessus gère tous les niveaux d'imbrication et de sous-collections. Il traite également le cas où un document a ses propres données et sous-collections. Ceci est basé sur l'hypothèse que la collection est un tableau/objet d'objets (y compris un objet vide ou un tableau).
Pour exécuter le script, assurez-vous que npm et le noeud sont installés. Ensuite, exécutez votre code en tant que node <name of the file>
. Notez qu'il n'est pas nécessaire de le déployer en tant que fonction cloud.
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 then it 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);
Vous avez besoin d'un script personnalisé pour le faire.
J'en ai écrit un basé sur le SDK d'administration Firebase, tant que la bibliothèque Firebase ne permet pas d'importer des tableaux nested.
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);
});
});
}
});
Mise à jour: J'ai écrit un article sur ce sujet - Remplir Firestore avec des données
Il n'y en a pas, vous aurez besoin d'écrire votre propre script pour le moment.
J'ai utilisé la solution générale fournie par Maciej Caputa. Je vous remercie (:
Voici quelques astuces. En supposant qu'une application Ionic Firebase soit installée avec les modules de nœud Firebase requis dans le dossier des fonctions de cette solution. Ceci est une installation standard de Ionic Firebase. J'ai créé un dossier d'importation pour contenir le script et les données au même niveau.
Hiérarchie des dossiers
myIonicApp
functions
node_modules
firebase-admin
ImportFolder
script.js
FirebaseIonicTest-a1b2c3d4e5.json
fileToImport.json
Paramètres de script
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
});
Création du fichier de clé du compte de service
J'ai simplement ajouté une clé au compte de service par défaut d'App Engine
La fonction Créer une clé proposera de télécharger la clé dans un fichier JSON.
Structure de données JSON
Pour utiliser le script fourni, la structure de données doit être la suivante:
{
"myCollection" : {
"UniqueKey1" : {
"field1" : "foo",
"field2" : "bar"
},{
"UniqueKey2" : {
"field1" : "fog",
"field2" : "buzz"
}...
}
Pour référence. J'ai écrit une fonction qui aide à importer et exporter des données dans Firestore.
https://Gist.github.com/JoeRoddy/1c706b77ca676bfc0983880f6e9aa8c8
Cela devrait fonctionner pour un objet ou un objet (en général, quel âge a firebase json est configuré). Vous pouvez ajouter ce code à une application déjà configurée avec Firestore.
Assurez-vous simplement qu'il pointe vers le bon fichier JSON.
Bonne chance!
Non, pour l’instant, vous ne pouvez pas .. Firestore structurer les données dans un format différent, à l’aide de collections. Chaque collection contient une série de documents qui sont ensuite stockés au format JSON. à Firestore .. pour référence vérifier ceci
: https://cloud.google.com/firestore/docs/concepts/structure-data
****MODIFIER :****
Vous pouvez automatiser le processus jusqu’à un certain point, c’est-à-dire écrire un logiciel fictif qui envoie uniquement les champs de vos données CSV ou JSON dans votre base de données Cloud Firestore. J'ai migré toute ma base de données pour créer une simple application qui récupérait ma base de données et la plaçait dans Firestore
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');
});
Il s'agit d'une petite modification qui copie le 'id' du document, s'il existe, sur son chemin. Sinon, il utilisera l'index "pour".
...
...
} 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);
Si les noms de vos collections ne sont pas uniquement composés de chiffres, vous pouvez définir le nom du document comme suit.
...
...
} 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]);
}
}
}
De la même manière que dans l'exemple ci-dessus, le nom de la sous-collection ne peut pas contenir que des chiffres.
...
...
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]);
}
}
...
...
Note .: Changements dans le code de @Maciej Caputa