Skip to content

Instantly share code, notes, and snippets.

@sturmenta
Last active October 28, 2022 19:03
Show Gist options
  • Star 48 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save sturmenta/cbbe898227cb1eaca7f85d0191eaec7e to your computer and use it in GitHub Desktop.
Save sturmenta/cbbe898227cb1eaca7f85d0191eaec7e to your computer and use it in GitHub Desktop.
firestore to json & json to firestore

The origin of this gist: https://blog.cloudboost.io/copy-export-a-cloud-firestore-database-388cde99259b

The schema is for example only, it's must be modified according to the firestore database.

Quoting Bruno Braga

"this schema is how your DB is organized in a tree structure. You don't have to care about the Documents but you do need to inform the name of your collections and any subcollections, in this case we have two collections called users and groups, the all have their documents, but the collection users has its own subcollections, friends and groups, which again have their own subcollection, messages."

For any doubt, add it here, but let me know by email that the question has been added, I usually go unnoticed when someone comments here.

sturmenta@gmail.com

const admin = require('firebase-admin');
const fs = require('fs');
const serviceAccount = require('../../../../../../Private/myschool-data_transfer-key.json');
admin.initializeApp({ credential: admin.credential.cert(serviceAccount) });
const schema = require('./schema').schema;
const firestore2json = (db, schema, current) => {
return Promise.all(
Object.keys(schema).map(collection => {
return db
.collection(collection)
.get()
.then(data => {
let promises = [];
data.forEach(doc => {
if (!current[collection]) current[collection] = { __type__: 'collection' };
current[collection][doc.id] = doc.data();
promises.push(
firestore2json(
db.collection(collection).doc(doc.id),
schema[collection],
current[collection][doc.id]
)
);
});
return Promise.all(promises);
});
})
).then(() => current);
};
firestore2json(admin.firestore(), { ...schema }, {}).then(res =>
fs.writeFileSync('./src/native_web/firebase/local_db.json', JSON.stringify(res, null, 2), 'utf8')
);
const admin = require('firebase-admin');
const fs = require('fs');
const serviceAccount = require('../../../../../../Private/myschool-data_transfer-key.json');
admin.initializeApp({ credential: admin.credential.cert(serviceAccount) });
const schema = require('./schema').schema;
const json2firestore = (_JSON, db, schema) => {
return Promise.all(
Object.keys(schema).map(collection => {
let promises = [];
Object.keys(_JSON[collection]).map(_doc => {
const doc_id = _doc;
if (_doc === '__type__') return;
let doc_data = Object.assign({}, _JSON[collection][_doc]);
Object.keys(doc_data).map(_doc_data => {
if (doc_data[_doc_data] && doc_data[_doc_data].__type__) delete doc_data[_doc_data];
});
promises.push(
db
.collection(collection)
.doc(doc_id)
.set(doc_data)
.then(() => {
return json2firestore(
_JSON[collection][_doc],
db.collection(collection).doc(doc_id),
schema[collection]
);
})
);
});
return Promise.all(promises);
})
);
};
json2firestore(
JSON.parse(fs.readFileSync('./src/native_web/firebase/local_db.json', 'utf8')),
admin.firestore(),
{ ...schema }
).then(() => console.log('done'));
exports.schema = {
all_users: {},
feedback: {},
reports: {},
schools: {
grades: {},
notifications: {},
publications: {},
users: {},
}
};
@andoma93
Copy link

andoma93 commented Aug 4, 2022

Workaround for dates:

const fixDates = (document) => {
  for (var key in document) {
    const val = document[key];

    if (val != null && val["_seconds"] != null && val["_nanoseconds"] != null) {
      document[key] = new admin.firestore.Timestamp(
        val["_seconds"],
        val["_nanoseconds"]
      );
    }
    if (val != null && val.constructor === Object) {
      fixDates(val);
    }
  }
  return document;
};

Then add doc_data = fixDates(doc_data); right before setting the data

This was not working for document with arrays and dates inside. Here the code fixed:

const fixDates = (document) => {
    for (var key in document) {
        const val = document[key];
        if (val != null && val["_seconds"] != null && val["_nanoseconds"] != null) {
            document[key] = new admin.firestore.Timestamp(
                   val["_seconds"],
                   val["_nanoseconds"]
            );
        }
        if (val != null && val.constructor === Object) {
            fixDates(val);
        }
        if (val != null && val.constructor === Array) {
            for(var arrayKey of val){
                fixDates(arrayKey);
            }
        }
    }
    return document;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment