【问题标题】:How to write data to cloud Firestore using cloud Functions如何使用云函数将数据写入云 Firestore
【发布时间】: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 编写云函数。任何帮助/提示将不胜感激!

【问题讨论】:

    标签: javascript firebase google-cloud-firestore google-cloud-functions


    【解决方案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

    【讨论】:

      猜你喜欢
      • 2018-07-25
      • 1970-01-01
      • 1970-01-01
      • 2020-03-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-13
      • 2020-03-26
      • 2021-01-18
      相关资源
      最近更新 更多