Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import CSV or JSON to firebase cloud firestore

Is there a way to import CSV or JSON to firebase cloud firestore like in firebase realtime database?

enter image description here

like image 895
Ted Avatar asked Oct 09 '17 07:10

Ted


People also ask

Does firestore use JSON?

Note: Cloud Firestore supports a variety of data types for values: boolean, number, string, geo point, binary blob, and timestamp. You can also use arrays or nested objects, called maps, to structure data within a document. You may notice that documents look a lot like JSON. In fact, they basically are.


2 Answers

General Solution

I've found many takes on a script allowing to upload a JSON but none of them allowed sub-collections. My script above handles any level of nesting and sub-collections. It also handles the case where a document has its own data and sub-collections. This is based on the assumption that collection is array/object of objects (including an empty object or array).

To run the script make sure you have npm and node installed. Then run your code as node <name of the file>. Note, there is no need to deploy it as a cloud funciton.

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); 
like image 161
Maciej Caputa Avatar answered Oct 16 '22 16:10

Maciej Caputa


You need a custom script to do that.

I wrote one based on the Firebase admin SDK, as long as firebase library does not allow you to import nested arrays of data.

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

Update: I wrote an article on this topic - Filling Firestore with data

like image 39
Mikki Kobvel Avatar answered Oct 16 '22 14:10

Mikki Kobvel