我正在构建一个Firebase函数,该函数可侦听触发器并将推送通知发送给用户。触发器基于Firestore数据,对于我来说,它太复杂,以至于每次都无法在Firestore模拟器上手动重新创建。
我尝试模拟函数,但是连接到Firestore生产,但是在这种情况下,触发函数似乎不起作用
我想要做的是从生产Firestore中导出数据,然后将其导入到仿真器Firestore中,这样至少,我正在使用的副本与我生产的产品非常相似;显然,数据很小,所以我不必担心下载TB级的数据。
我找到了way of importing data into an emulator,但不确定是否可以用于生产数据或如何从生产中转储数据。
firebase emulators:start --import=./some-directory
答案 0 :(得分:3)
您可以从生产中手动导出,然后导入到Firestore模拟器中。
首先将生产数据导出到文件。在该示例中,我仅在onRequest函数中导出“用户”集合,因此可以通过调用URL开始。请注意,此功能将无法处理子集合。
exports.exportFirestore = functions.https.onRequest(async (req, res) => {
const fs = require("fs");
const collection = "users";
const fileName = "fs-export.json";
const exportedData = {};
exportedData[collection] = {};
await admin
.firestore()
.collection(collection)
.get()
.then((snapshot) => {
return snapshot.forEach((doc) => {
exportedData[collection][doc.id] = doc.data();
});
})
.catch(console.error);
fs.writeFile(fileName, JSON.stringify(exportedData), (err) => {
if (err) {
console.log(err);
} else {
console.log("Firestore Export Complete.");
res.send("Firestore Export Complete.");
}
});
});
接下来,将文件导入本地Firestore模拟器。 非常重要:请确保运行Firestore模拟器,否则您将数据导入回产品中。确保通过检查以下Web UI来检查Firestore是否正在运行:http://localhost:4000。使用以下命令启动仿真器:firebase emulators:start
exports.importFirestore = functions.https.onRequest(async (req, res) => {
const fs = require("fs");
let collection;
const fileName = "fs-export.json";
const exportedData = {};
exportedData[collection] = {};
fs.readFile(fileName, "utf8", async (err, data) => {
if (err) {
return console.log(err);
}
const arr = JSON.parse(data);
const batch = admin.firestore().batch();
for (let i in arr) {
collection = i;
for (let doc in arr[i]) {
if (arr[i].hasOwnProperty(doc)) {
const ref = admin.firestore().collection(collection).doc(doc);
batch.set(ref, arr[i][doc]);
} else {
console.log("Missing:", JSON.stringify(doc, null, 2));
}
}
}
await batch
.commit()
.then(() => {
return console.log("Import to Firestore Complete");
})
.catch(console.error);
return res.send("Import to Firestore Complete");
});
});
答案 1 :(得分:0)
我的答案在很大程度上受到@Geoffrey Bourne答案的启发,但我不得不修改一些内容并找出更多细节才能使它起作用。
首先,我将exportFirestore
上传到Cloud Functions(生产)。当我通过此URL https://us-central1-<project-id>.cloudfunctions.net/exportFirestore
运行它时,由于云功能为read-only
以下代码用于一个名为fl_content
的集合,我将考虑将其扩展到多个集合
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();
});
})
一旦下载了文件fire-export.json
,将其放在functions
文件夹中。然后打开导入功能的URL(本地)http://localhost:5001/<project-id>/us-central1/importFirestore
。确保collection
变量在导出和导入中相同。
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");
});
});