Skip to content

Instantly share code, notes, and snippets.

@ken-itakura
Created June 14, 2020 10:06
Show Gist options
  • Save ken-itakura/3d150907be79dfbacc1eb1a614a38dc4 to your computer and use it in GitHub Desktop.
Save ken-itakura/3d150907be79dfbacc1eb1a614a38dc4 to your computer and use it in GitHub Desktop.
export and import firestore document tree (typescript). env var GOOGLE_APPLICATION_CREDENTIALS must be defined before run
import {Firestore} from "@google-cloud/firestore";
import fs from "fs";
const firestore = new Firestore();
const keyOriginalPath = "__originalPath__";
const keyDocumentContent = "__documentContent__";
const keyCollectionPath = "__collectionPath__";
const keyCollections = "__collections__";
const keyDocument= "__document__";
if(process.argv.length !== 5){
console.log('Please specify "mode", "firestore root path" and "output/input file name"');
console.log(`USAGE: ${process.argv[0]} ${process.argv[1]} [export|import] root_path [output_file|input_file]`);
process.exit(1);
}
const mode = process.argv[2];
const documentPath = process.argv[3];
const fileName = process.argv[4];
async function get_document_tree(path: string) {
// console.log(`Get Tree ${path}`)
const docRef = firestore.doc(path);
const snapshot = await docRef.get();
const docContent = await snapshot.data();
const collectionRefs = await docRef.listCollections();
const collectionIds = collectionRefs.map((c: any) => {return c.id});
const collectionContents = [];
for(const collectionId of collectionIds){
const documents = await docRef.collection(collectionId).listDocuments();
for(const document of documents){
const documentTree:any = await get_document_tree(`${path}/${collectionId}/${document.id}`);
collectionContents.push({[keyCollectionPath]:`${collectionId}/${document.id}`,[keyDocument]: documentTree});
}
}
return {[keyOriginalPath]: path, [keyDocumentContent]: docContent, [keyCollections]: collectionContents};
}
async function do_export() {
return await get_document_tree(documentPath);
}
async function create_document_tree(path: string, data:any){
const docRef = firestore.doc(path);
// console.log(`Importing data of ${data[keyOriginalPath]} to ${path}`);
await docRef.set(data[keyDocumentContent]);
for(const collectionDocument of data[keyCollections]){
await create_document_tree(`${path}/${collectionDocument[keyCollectionPath]}`,
collectionDocument[keyDocument])
}
}
async function do_import(){
const data = fs.readFileSync(fileName, "utf8");
await create_document_tree(documentPath, JSON.parse(data));
}
if(mode==="export") {
console.log(`Exporting ${documentPath} to ${fileName}`);
do_export().then((result: any) => {
const json = JSON.stringify(result);
console.log(json);
fs.writeFile(fileName, json, (err: any) => {
if (err) console.log(`File output error : ${err}`);
});
}).catch((reason: any) => {
console.log(`Export error by ${reason}`)
});
}
else if(mode==="import"){
console.log(`Importing ${fileName} to ${documentPath}`);
do_import().then(() => {
console.log("Completed.");
}).catch((reason:any)=>{
console.log(`Import error by ${reason}`)
})
}
else{
console.log(`invalid mode ${mode}`);
process.exit(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment