My answer is heavily inspired by @Geoffrey Bourne's answer, but I had to modify some stuff and figure out more details to get it working.
First, I upload the exportFirestore
to Cloud Functions (production). When I run it through this URL https://us-central1-<project-id>.cloudfunctions.net/exportFirestore
, I get a file DOWNLOADED, as Cloud Functions are read-only
The below code is for one collection named fl_content
, I'll consider expanding it to multiple collections
export const exportFirestore = functions.https.onRequest(async (req, res) => {
const collection = "fl_content";
const exportedData: any = {};
exportedData[collection] = {};
await admin
.firestore()
.collection(collection)
.get()
.then((snapshot) => snapshot.forEach((doc) => exportedData[collection][doc.id] = doc.data()))
.catch(console.error);
const data = JSON.stringify(exportedData);
res.setHeader('Content-disposition', 'attachment; filename=fire-export.json');
res.setHeader('Content-type', 'application/json');
res.write(data, function () {
res.end();
});
})
Once you have the file fire-export.json
downloaded, put it inside the functions
folder. Then open the URL for the import function (locally) http://localhost:5001/<project-id>/us-central1/importFirestore
. Make sure the collection
variable is the same in the export and import.
export const importFirestore = functions.https.onRequest(async (req, res) => {
const fs = require("fs");
const collection = "fl_content";
const fileName = "fire-export.json";
const exportedData: any = {};
exportedData[collection] = {};
fs.readFile(fileName, "utf8", async (err: any, data: any) => {
if (err) {
res.send(err);
functions.logger.error(err)
return;
}
const arr = JSON.parse(data);
const batch = admin.firestore().batch();
for (const i in arr) {
for (const doc in arr[i]) {
if (arr[i].hasOwnProperty(doc)) {
const ref = admin.firestore().collection(collection).doc(doc);
batch.set(ref, arr[i][doc]);
} else {
functions.logger.error("Missing:", JSON.stringify(doc, null, 2));
}
}
}
await batch
.commit()
.then(() => console.log("Import to Firestore Complete"))
.catch(console.error);
res.send("Import to Firestore Complete");
});
});