Cloud Firestore 触发器

借助 Cloud Functions,您可以处理 Cloud Firestore 中的事件,而无需更新客户端代码。您可以通过 DocumentSnapshot 接口或通过 Admin SDK 进行 Cloud Firestore 更改。

在一个典型的生命周期中,Cloud Firestore 函数会执行以下工作:

  1. 等待特定文档发生更改。
  2. 在有事件发生时触发并执行相应的任务(请参阅 Cloud Functions 有哪些用途?,了解使用情形示例) 。
  3. 接收包含了存储在指定文档中的数据快照的数据对象。对于 onWriteonUpdate 事件,该数据对象包含两个快照,分别代表触发事件前后的数据状态。

Firestore 实例的位置与函数位置之间的距离可能会产生严重的网络延迟。为了优化性能,请考虑在适用情况下指定函数位置

触发 Cloud Firestore 函数

Cloud Functions for Firebase SDK 会导出一个 functions.firestore 对象,使您能够创建与特定事件绑定的处理程序。

Cloud Firestore 支持 createupdatedeletewrite 事件:

事件类型 触发器
onCreate 首次写入某个文档时触发。
onUpdate 当某文档已存在并且发生了任何值更改时触发。
onDelete 当文档的数据被删除时触发。
onWrite 当触发了 onCreateonUpdateonDelete 时触发。

如果您还没有启用了 Cloud Functions for Firebase 的项目,请阅读使用入门:编写和部署您的第一批函数,配置并设置您的 Cloud Functions for Firebase 项目。

当特定文档发生更改时触发函数

如果您希望针对特定文档的任何更改都触发一个事件,则可以使用以下函数。

Node.js

// Listen for any change on document `marie` in collection `users`
exports.myFunctionName = functions.firestore
    .document('users/marie').onWrite((change, context) => {
      // ... Your code here
    });

在创建新文档时触发函数

您可以使用带通配符onCreate() 处理程序,触发一个在集合中新建文档时触发的函数。每次添加了新的用户个人资料时,此示例函数在都会调用 createUser

Node.js

exports.createUser = functions.firestore
    .document('users/{userId}')
    .onCreate((snap, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = snap.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

在文档更新时触发函数

您可以使用带通配符onUpdate() 函数,触发一个在更新文档时触发的函数。此示例函数会在用户更改其个人资料时调用 updateUser

Node.js

exports.updateUser = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

当文档被删除时触发函数

您还可以使用带通配符onDelete() 函数,触发一个在删除文档时触发的函数。当用户删除其用户个人资料时,此示例函数会调用 deleteUser

Node.js

exports.deleteUser = functions.firestore
    .document('users/{userID}')
    .onDelete((snap, context) => {
      // Get an object representing the document prior to deletion
      // e.g. {'name': 'Marie', 'age': 66}
      const deletedValue = snap.data();

      // perform desired operations ...
    });

在文档发生任何更改时触发函数

如果您不在意触发的事件类型,则可以使用带通配符onWrite() 函数来侦听 Cloud Firestore 文档中的所有更改。当有用户被创建、更新或删除时,此示例函数会调用 modifyUser

Node.js

exports.modifyUser = functions.firestore
    .document('users/{userID}')
    .onWrite((change, context) => {
      // Get an object with the current document value.
      // If the document does not exist, it has been deleted.
      const document = change.after.exists ? change.after.data() : null;

      // Get an object with the previous document value (for update or delete)
      const oldDocument = change.before.data();

      // perform desired operations ...
    });

处理事件数据

读取数据

函数触发后,您可能希望获取更新后文档的数据,或者获取更新之前的数据。您可以通过使用 change.before.data() 来获取之前的数据,其中包含更新前的文档快照。同样,change.after.data() 包含更新后的文档快照状态。

Node.js

exports.updateUser = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the current document
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();
    });

您可以像在其他任何对象中一样访问属性。或者,您可以使用 get 函数访问特定字段:

Node.js

// Fetch data using standard accessors
const age = snap.data().age;
const name = snap.data()['name'];

// Fetch data using built in accessor
const experience = snap.get('experience');

写入数据

每个函数调用都与 Cloud Firestore 数据库中的特定文档相关联。您可以在为函数返回的快照的 ref 属性中以 DocumentReference 的形式访问该文档。

DocumentReference 来自 Cloud Firestore Node.js SDK,包含 update()set()remove() 等方法,因此您可以轻松修改触发了相应函数的文档。

Node.js

// Listen for updates to any `user` document.
exports.countNameChanges = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Retrieve the current and previous value
      const data = change.after.data();
      const previousData = change.before.data();

      // We'll only update if the name has changed.
      // This is crucial to prevent infinite loops.
      if (data.name == previousData.name) return null;

      // Retrieve the current count of name changes
      let count = data.name_change_count;
      if (!count) {
        count = 0;
      }

      // Then return a promise of a set operation to update the count
      return change.after.ref.set({
        name_change_count: count + 1
      }, {merge: true});
    });

使用通配符和参数

如果您不知道要向其附加事件触发器的具体文档,可以使用一个 {wildcard} 取代文档 ID。

Node.js

// Listen for changes in all documents and all sub-collections
exports.useWildcard = functions.firestore
    .document('users/{userId}')
    .onWrite((change, context) => {
      // If we set `/users/marie` to {name: "marie"} then
      // context.params.userId == "marie"
      // ... and ...
      // change.after.data() == {name: "Marie"}
    });

在此示例中,如果 users 中的任何文档的任何字段发生更改,都会与一个名为 userId 的通配符相匹配。

如果 users 中的某个文档有多个子集合,并且这些子集合中的某个文档内的某字段发生了更改,则不会触发 userId 通配符。

通配符匹配项会从文档路径中提取出来并存储至 event.params。您可以定义任意多个通配符,以替代明确指定的集合或文档 ID。

Node.js

// Listen for changes in all documents and all subcollections
exports.useMultipleWildcards = functions.firestore
    .document('users/{userId}/{messageCollectionId}/{messageId}')
    .onWrite((change, context) => {
      // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then
      // context.params.userId == "marie";
      // context.params.messageCollectionId == "incoming_messages";
      // context.params.messageId == "134";
      // ... and ...
      // change.after.data() == {body: "Hello"}
    });

限制和保证

在开发应用时,请注意,Cloud Firestore 目前都处于测试阶段,可能会导致意外的行为。

一些已知的限制包括:

  • Cloud Firestore 数据发生更改后,最长可能需要 10 秒钟才会触发函数。
  • 与所有后台函数一样,事件排序是无法保证的。此外,单个事件可能会导致出现多次 Cloud Functions 调用,因此,为了保证实现最高质量的函数,在编写函数时请务必遵循幂等原则。

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面