如何使用云函数将数据写入云 Firestore
Posted
技术标签:
【中文标题】如何使用云函数将数据写入云 Firestore【英文标题】:How to write data to cloud Firestore using cloud Functions 【发布时间】:2020-03-04 03:46:20 【问题描述】:对于我在 Flutter 中构建的调度应用程序,我正在尝试使用云功能和 cron 作业将数据写入我的云 Firestore 数据库,以使我的应用程序更加自我维持。我被困在第一步,试图让我的云功能将数据写入我的云 Firestore 数据库。
下面我在 github 上包含了指向图片的链接,这些图片说明了我当前数据在 Firestore 中的结构。我想要的是将命名文档添加到具有“小时”子集合的“天”集合中,其中有更多具有“小时”和“保留”字段的命名文档。
图一:https://github.com/winckles/rooster/blob/master/Schermafbeelding%202019-11-07%20om%2014.27.55.png?raw=true
图二:https://github.com/winckles/rooster/blob/master/Schermafbeelding%202019-11-07%20om%2014.28.26.png?raw=true
下面我还介绍了我在 Firestore 中获取数据的尝试。
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// admin.firestore().collection('days').add(original: original). then(writeResult =>
//
// );
exports.updateData = functions.https.onCall((data, context) =>
const days = admin.firestore().collection('days');
return days.doc(data['2019-11-08/hours/001']).set(
hour: '08:00-09:00',
reserved: '',
);
);
理想情况下,我希望云功能同时将 14 个文档(例如 2019-11-06 到 2019-11-19)添加到“days”集合中。然后,这些文档每个都有一个子集合“小时”,其中包含来自第二个屏幕截图的数据(因此文档 001、002、003 等具有小时和保留字段)。
我阅读了有关云功能的文档,并且大部分发现了将数据写入 Firestore 时的触发器,但这不是我想要的。我还尝试了快速入门功能示例,但没有成功。它不应该太难,但我似乎无法弄清楚。我正在使用 javascript 编写云函数。任何帮助/提示将不胜感激!
【问题讨论】:
【参考方案1】:你没有具体说明什么不适合你。但是,我注意到的第一件事是您没有从云函数上下文中正确调用initilizeApp
。对于云函数,您不需要任何参数,因为默认凭据应该适合您(除非您已经做了一些非常不寻常的事情)。
这是一个云函数,可以对您想要的行为进行建模。它没有完成全部行为,因为我发现编写日期处理代码可能会分散您所询问问题的主要部分,即 Firestore 和函数代码本身。
同样,这使用 https 函数(因为它对我来说更容易测试:),使用可调用函数(或任何其他函数类型,例如,如果您使用的是 cron 作业,则为预定函数)需要稍微调整它(例如,对于可调用函数,您需要将声明更改回 onCall
并更改最终的 .then()
调用以返回您想要返回的值)。
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.doIt = functions.https.onRequest((request, response) =>
const days = db.collection('days');
const writePromises = [];
['2019-11-08', '2019-11-09'].forEach((day) =>
const documentReference = days.doc(day);
writePromises.push(documentReference.set(reserved: ''));
const hoursReference = documentReference.collection('hours');
const dataMap = '001': '08:00-09:00',
'002': '09:00-10:00',
'003': '10:00-11:00',
'004': '11:00-12:00' ;
Object.keys(dataMap).forEach((hour) =>
writePromises.push(hoursReference.doc(hour).set(
hour: dataMap[hour],
reserved: ''
))
);
);
return Promise.all(writePromises)
.then(() => response.send('ok'); )
.catch((err) => console.log(err); );
);
请注意,当您编写整个结构时,您需要为每个文档的写入付费。但实际上并没有办法避免这种情况,因为写入是按文档计费的,而不是按请求计费的。
同样,您可能需要考虑将其作为batched write 执行——上面的示例只是展示了一种基本的写作方法。批量写入会将所有文档自动放入数据库。但是,批量写入限制为 500 次更新,您将在大约 21 天的数据(21 天 * 24 小时)内达到这些更新。这看起来与上面非常相似(以下只是函数本身的内容:
const days = db.collection('days');
const batch = db.batch();
['2019-11-08', '2019-11-09'].forEach((day) =>
const documentReference = days.doc(day);
batch.set(documentReference, reserved: '');
const hoursReference = documentReference.collection('hours');
const dataMap = '001': '08:00-09:00',
'002': '09:00-10:00',
'003': '10:00-11:00',
'004': '11:00-12:00' ;
Object.keys(dataMap).forEach((hour) =>
batch.set(hoursReference.doc(hour),
hour: dataMap[hour],
reserved: ''
);
);
);
return batch.commit()
.then(() => response.send('ok'); )
.catch((err) => console.log(err); );
我确实有点想知道为什么您需要在云功能中执行此操作,而不是通过直接从您的应用程序调用 Firestore。无论如何,以上内容应该可以让您开始。
【讨论】:
太棒了,谢谢你的作品!我还有一个问题;如果我希望 001、002 等的时间完全不同(例如,001 的时间为 08:00-09:00,002 的时间为 09:00-10:00),那在代码中会怎样?至于为什么不是直接从应用程序调用;我认为 cronjobs 仅适用于云功能,并且我认为当代码的更改只能通过应用商店完成时,以这种方式进行更新会更容易。总而言之,我只是一个试图让mvp启动并运行的菜鸟,我会调查你所说的!再次感谢! 我省略了这部分,因为 (a) 它增加了答案中隐藏的复杂性(正如我所提到的),但此外 (b) 我无法为 '005' 想出任何合理的方法成为“12:00-13:00”(来自您的示例图像),而不仅仅是通过硬编码映射。但是,您可以通过将关联数组作为映射并在内部循环中循环其键/值而不是平面数组来做到这一点。我将添加一个示例。 非常感谢!我已经为此苦苦挣扎了一段时间,而您刚刚解决了!这是让我的 mvp 启动和运行的一大步,你甚至无法想象!【参考方案2】:如果您想在 firebase 中执行 cron,使用 Google Cloud Scheduler 可能会更好,但要小心这种方法有不同的分解
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) =>
console.log('This will be run every 5 minutes!');
return null;
);
您可以在以下位置了解更多信息:
https://firebase.google.com/docs/functions/schedule-functions
【讨论】:
以上是关于如何使用云函数将数据写入云 Firestore的主要内容,如果未能解决你的问题,请参考以下文章
您如何避免使用 firebase 云功能可能出现的竞争情况?