【问题标题】:Cloud functions to update data from Realtime to firestore将数据从实时更新到 Firestore 的云功能
【发布时间】:2021-05-29 10:41:48
【问题描述】:

我在实时数据库中有一些数据来自 IOT 传感器我想将一些数据存储在 Firestore 中我做了这段代码

exports.addtoFirestore = functions.database.ref('lamps/{id}').onWrite(async (snapshot, context) => {
    const val = snapshot.val();
    const id = snapshot.key;

    return admin.firestore().collection('lamps').doc(id).update({
        Humidity: val.Humidity,
        Temperature: val.Temperature
      });

    

     


});

但函数控制台打印 **函数执行耗时 76 毫秒,完成状态为:'error' ** 更新实时数据库时

【问题讨论】:

    标签: firebase firebase-realtime-database google-cloud-firestore


    【解决方案1】:

    您的代码存在三个主要问题:

    • 通过使用 DocumentReference#update(newData) 将更改与 Cloud Firestore 同步,如果您的 Cloud Firestore 中不存在 /lamps/{id} 文档,您的代码将引发错误。
    • 由于您使用的是onWrite() RTDB触发器,您需要处理云函数指向的数据已被删除的情况。目前,如果您的函数不存在(如val == null),则会出错。
    • 如果传入数据中省略了 HumidityTemperature(区分大小写!),尝试将其数据添加到 Cloud Firestore(将为 undefined)将引发有关无效数据类型的错误。

    对此最简单的解决方法是酌情使用DocumentReference#set(newData, { merge: true })DocumentReference#delete(),同时使用suitable security rules 保护您的RTDB,以确保您的传入数据形状良好。

    import * as admin from "firebase-admin";
    import * as functions from "firebase-functions";
    admin.initializeApp();
    
    exports.addtoFirestore = functions.database.ref('lamps/{id}').onWrite(async (snapshot, context) => {
      const id = snapshot.key;
      const docRef = admin.firestore().collection('lamps').doc(id);
    
      if (!snapshot.exists) {
        // data deleted, delete linked Firestore data
        return docRef.delete()
          .catch((error) => {
            console.error(`Failed to sync data deletion for /lamps/${id}: `, error);
    
            // optionally rethrow it:
            // throw error;
          });
      }
    
      const { Humidity, Temperature } = snapshot.val();
      return docRef.set({ Humidity, Temperature }, { merge: true })
        .catch((error) => {
          console.error(`Failed to sync data to Firestore for /lamps/${id}: `, error);
    
          // optionally rethrow it:
          // throw error;
        });
    });
    

    确保实施相关的安全规则:

    {
      "rules": {
        "lamps": {
          "$lampId": {
            // must be logged in to read/write
            // because we restrict this heavily below, you
            // could make this "true", but I don't recommend it
            ".write": "auth != null",
            ".read": "auth != null",
    
            "Humidity": {
              // if present, must be number
              ".validate": "newData.isNumber()"
            },
            "Temperature": {
              // if present, must be number
              ".validate": "newData.isNumber()"
            },
            "$other": {
              // block all other data
              ".validate": "false"
            }
          }
        }
      }
    }
    

    其他说明:

    • 即使进行了上述更改,您也可以在同一个项目中同时使用 Cloud Firestore 和 RTDB,因此您可以完全取消此同步功能,只需连接到客户端上的两个数据库即可。这将减少因使用此功能而产生的任何不同步问题。
    • 如果您希望有多个传感器同时更新 RTDB,您还可以考虑使用 scheduled to run every X minutes 或公开 HTTP endpoint 的按需“同步更改”功能,以降低同步更改的频率。李>

    【讨论】:

      猜你喜欢
      • 2020-08-02
      • 2019-12-13
      • 2019-08-26
      • 1970-01-01
      • 2020-03-12
      • 2021-03-27
      • 2020-02-01
      • 2018-06-30
      • 2021-12-03
      相关资源
      最近更新 更多