web-dev-qa-db-fra.com

Comment importer un fichier CSV ou JSON dans une base de feu sur un nuage de Firebase

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?

 enter image description here

37
Ted

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);
43
Maciej Caputa

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

15
Mikki

Il n'y en a pas, vous aurez besoin d'écrire votre propre script pour le moment.

7
Dan McGrath

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

 Domain name from the Hosting tab

Création du fichier de clé du compte de service

  • Dans la console Firebase de votre projet, en regard de l'élément Project Overwiew, cliquez sur l'icône en forme d'engrenage et sélectionnez Utilisateurs et autorisations
  • Au bas de l'écran, cliquez sur Autorisation avancée Paramètres

 Accessing Google Cloud Platform Console

  • Cela ouvre un autre onglet pour la console Google Cloud Platform.
  • Sur la gauche, sélectionnez l'élément Comptes de service.
  • Créer un compte de service pour un compte de service existant

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.

 Creating the Service Account Key

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"
    }...
}
6
pasx

Pour référence. J'ai écrit une fonction qui aide à importer et exporter des données dans Firestore. 

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

4
Dale Nguyen

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!

1
Joe Roddy

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

1
Anubhav Malik
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');
  });
0
Atit Timilsina

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);
0
rgrcnh

1 - Importer uniquement des collections

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

2 - Importer des collections et des sous-collections

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

0
Bruno Henrique