How to import CSV or JSON to firebase cloud firestore

前端 未结 11 1045
星月不相逢
星月不相逢 2020-11-29 16:19

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

11条回答
  •  抹茶落季
    2020-11-29 16:54

    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 . 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://.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);
    

提交回复
热议问题