获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

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 事件的处理程序。

事件类型扳机
onCreate第一次写入文档时触发。
onUpdate当文档已经存在并且任何值已更改时触发。
onDelete删除包含数据的文档时触发。
onWrite在触发onCreateonUpdateonDelete时触发。

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

编写 Cloud Firestore 触发的函数

定义函数触发器

要定义 Cloud Firestore 触发器,请指定文档路径和事件类型:

节点.js

const functions = require('firebase-functions');

exports.myFunction = functions.firestore
  .document('my-collection/{docId}')
  .onWrite((change, context) => { /* ... */ });

文档路径可以引用特定文档通配符模式

指定单个文档

如果您想为特定文档的任何更改触发事件,则可以使用以下功能。

节点.js

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

使用通配符指定一组文档

如果要将触发器附加到一组文档,例如某个集合中的任何文档,请使用{wildcard}代替文档 ID:

节点.js

// Listen for changes in all documents in the 'users' collection
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通配符。

通配符匹配从文档路径中提取并存储到context.params中。您可以定义任意数量的通配符来替换显式集合或文档 ID,例如:

节点.js

// Listen for changes in all documents in the 'users' collection 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"}
    });

事件触发器

创建新文档时触发函数

通过使用带有通配符onCreate()处理程序,您可以在集合中创建新文档时随时触发函数。每次添加新用户配置文件时,此示例函数都会调用createUser

节点.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

节点.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

节点.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

节点.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 ...
    });

读写数据

触发功能时,它会提供与事件相关的数据快照。您可以使用此快照读取或写入触发事件的文档,或使用 Firebase Admin SDK 访问数据库的其他部分。

事件数据

读取数据

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

节点.js

exports.updateUser2 = 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函数访问特定字段:

节点.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()等方法,因此您可以轻松修改触发该功能的文档。

节点.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});
    });

触发事件之外的数据

Cloud Functions 在受信任的环境中执行,这意味着它们被授权为您项目的服务帐户。您可以使用Firebase Admin SDK执行读取和写入:

节点.js

const admin = require('firebase-admin');
admin.initializeApp();

const db = admin.firestore();

exports.writeToFirestore = functions.firestore
  .document('some/doc')
  .onWrite((change, context) => {
    db.doc('some/otherdoc').set({ ... });
  });

限制

请注意 Cloud Functions 的 Cloud Firestore 触发器的以下限制:

  • 不能保证订购。快速更改可能会以意想不到的顺序触发函数调用。
  • 事件至少传递一次,但单个事件可能会导致多个函数调用。避免依赖于 exactly-once 机制,并编写幂等函数
  • Cloud Functions 的 Cloud Firestore 触发器仅适用于 Native 模式下的 Cloud Firestore。它不适用于 Datastore 模式下的 Cloud Firestore。