欢迎参加我们将于 2022 年 10 月 18 日举办的 Firebase 峰会(线上线下同时进行),了解 Firebase 如何帮助您加快应用开发速度、满怀信心地发布应用并在之后需要时轻松地扩大应用规模。立即报名

实时数据库触发器

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

在典型的生命周期中,Firebase 实时数据库函数会执行以下操作:

  1. 等待对特定实时数据库路径的更改。
  2. 当事件发生并执行其任务时触发。
  3. 接收包含存储在该路径的数据快照的数据对象。

您可以触发函数以响应 Firebase 实时数据库中数据库节点的写入、创建、更新或删除。

触发 Firebase 实时数据库更改的函数

使用firebase-functions/v2/database子包创建处理 Firebase 实时数据库事件的函数。要控制函数何时触发,请指定事件处理程序之一,并指定它将侦听事件的实时数据库路径。

设置功能位置

实时数据库实例的位置与函数的位置之间的距离可能会产生显着的网络延迟。此外,区域之间的不匹配可能会导致部署失败。为避免这些情况,请指定函数位置,使其与数据库实例位置相匹配。

处理实时数据库事件

函数让您可以在两个特定级别处理实时数据库事件;您可以专门针对写入、创建、更新或删除事件进行侦听,或者您可以侦听对引用的任何类型的任何更改。

这些用于响应实时数据库事件的处理程序可用:

  • onValueWritten()仅在数据写入实时数据库时触发。
  • onValueCreated()仅在实时数据库中创建数据时触发。
  • onValueUpdated()仅在实时数据库中更新数据时触发。
  • onValueDeleted()仅在实时数据库中删除数据时触发。

指定实例和路径

要控制函数应触发的时间和位置,请使用路径和可选的实时数据库实例配置函数。如果您不指定实例,则该函数将部署到该函数区域中的所有实时数据库实例。您还可以指定实时数据库实例模式以部署到同一区域中的选择性实例子集。

例如,使用onValueWritten()进行说明:

# All Realtime Database instances in default function region us-central1 at path "/user/{uid}"
# There must be at least one Realtime Database present in us-central1.
const onwrittenfunctiondefault = onValueWritten("/user/{uid}", (event) => {
  // …
});

# Instance named "my-app-db-2", at path "/user/{uid}".
# The "my-app-db-2" instance must exist in this region.
const onwrittenfunctioninstance = onValueWritten(
  {
    ref: "/user/{uid}",
    instance: "my-app-db-2"
    // This example assumes us-central1, but to set location:
    // region: "europe-west1"
  },
  (event) => {
    // …
  }
);

# Instance with "my-app-db-" prefix, at path "/user/{uid}", where uid ends with @gmail.com.
# There must be at least one Realtime Database with "my-app-db-*" prefix in this region.
const onwrittenfunctioninstance = onValueWritten(
  {
    ref: "/user/{uid=*@gmail.com}",
    instance: "my-app-db-*"
    // This example assumes us-central1, but to set location:
    // region: "europe-west1"
  },
  (event) => {
    // …
  }
);

这些参数指示您的函数处理实时数据库实例中特定路径的写入。

路径规范匹配所有触及路径的写入,包括发生在其下方任何位置的写入。如果您将函数的路径设置为/foo/bar ,它将匹配以下两个位置的事件:

 /foo/bar
 /foo/bar/baz/really/deep/path

在任何一种情况下,Firebase 都会解释事件发生在/foo/bar ,并且事件数据包括/foo/bar的旧数据和新数据。如果事件数据可能很大,请考虑在更深的路径中使用多个函数,而不是在数据库根附近使用单个函数。为获得最佳性能,请仅在可能的最深级别请求数据。

通配符和捕获

您可以使用{key}{key=*}{key=prefix*}{key=*suffix}进行捕获。 * , prefix* , *suffix用于单段通配符。注意: **表示多段通配符,RTDB 不支持。请参阅了解路径模式

路径通配符。您可以将路径组件指定为通配符:

  • 使用星号* 。例如, foo/*匹配 foo foo/下一级节点层次结构的任何子节点。
  • 使用包含完全星号的段, * 。例如, foo/app*-us匹配foo/以下的任何子段,带有app前缀和-us后缀。

带有通配符的路径可以匹配来自例如单个写入的多个事件。一个插入

{
  "foo": {
    "hello": "world",
    "firebase": "functions"
  }
}

匹配路径"/foo/*"两次:一次与"hello": "world"匹配,再次与"firebase": "functions"匹配。

路径捕获。您可以将路径匹配捕获到要在函数代码中使用的命名变量中(例如/user/{uid}/user/{uid=*-us} )。

捕获变量的值在函数的database.DatabaseEvent.params对象中可用。

实例通配符。您还可以使用通配符指定实例组件。实例通配符可以有前缀、后缀或两者兼有(例如my-app-*-prod )。

通配符和捕获参考

使用 Cloud Functions v2 和实时数据库,可以在指定refinstance时使用模式。每个触发器接口将具有以下用于确定函数范围的选项:

指定ref指定instance行为
单人( /foo/bar未指定范围处理程序到功能区域中的所有实例。
单人( /foo/bar单( 'my-new-db'范围处理程序到函数区域中的特定实例。
单人( /foo/bar模式( 'inst-prefix*'范围处理程序到与函数区域中的模式匹配的所有实例。
模式( /foo/{bar}未指定范围处理程序到功能区域中的所有实例。
模式( /foo/{bar}单( 'my-new-db'范围处理程序到函数区域中的特定实例。
模式( /foo/{bar}模式( 'inst-prefix*'范围处理程序到与函数区域中的模式匹配的所有实例。

处理事件数据

处理实时数据库事件时,返回的数据对象是DataSnapshot

对于onValueWrittenonValueUpdated事件,第一个参数是一个Change对象,其中包含两个快照,表示触发事件之前和之后的数据状态。

对于onValueCreatedonValueDeleted事件,返回的数据对象是创建或删除数据的快照。

在此示例中,该函数将指定路径foo/bar的快照检索为snap ,将该位置的字符串转换为大写,并将修改后的字符串写入数据库:

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
export makeuppercase = onValueCreated("foo/bar", (event) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = event.data.val();
      functions.logger.log('Uppercasing', event.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return event.data.ref.parent.child('uppercase').set(uppercase);
    });

读取前一个值

Change对象有一个before属性,可让您检查在事件之前保存到实时数据库的内容。 before属性返回一个DataSnapshot ,其中所有方法(例如val()exists() )都引用前一个值。您可以使用原始DataSnapshot或读取after属性再次读取新值。任何Change上的此属性都是另一个DataSnapshot ,表示事件发生数据的状态。

例如, before属性可用于确保函数在首次创建时仅将大写文本:

    exports makeuppercase = onValueWritten("/messages/{pushId}/original", (event) => {
          // Only edit data when it is first created.
          if (event.data.before.exists()) {
            return null;
          }
          // Exit when the data is deleted.
          if (!event.data.after.exists()) {
            return null;
          }
          // Grab the current value of what was written to the Realtime Database.
          const original = event.data.after.val();
          console.log('Uppercasing', event.params.pushId, original);
          const uppercase = original.toUpperCase();
          // You must return a Promise when performing asynchronous tasks inside a Functions such as
          // writing to the Firebase Realtime Database.
          // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
          return event.data.after.ref.parent.child('uppercase').set(uppercase);
        });