首页 > 解决方案 > 在 Cloud Firestore 上添加文档时更新字段

问题描述

我有一个关于在我的 Android 应用程序中使用 Cloud Firestore 函数的问题(我正在使用 Android Studio 在 kotlin 上写作)

阅读了一些文档后,我认为在我的数据库中创建新文档时,可以在 Firestore Functions 中运行自定义方法。我需要做的就是更新一个字段。

问题是 Cloud Firestore 上的这些功能需要用 JavaScript 编写,我需要使用 Node.js,而我对此一无所知。

对于任何具有 Cloud Firestore 知识的开发人员,有关此问题的任何指南或提示?

标签: node.jsfirebasegoogle-cloud-firestore

解决方案


问题是 Cloud Firestore 上的这些功能需要用 JavaScript 编写,我需要使用 Node.js,而我对此一无所知。

不知道它是否有帮助,但 Cloud Functions 也可以用 Python 或 Go 编写。您可以在此处查看有关当前运行时和语言的更多完整信息。

但是让我们试着回答你的问题,好吗?我将在下面的示例中使用 Node.js 8 运行时。

介绍

Google Cloud Functions 目前支持 2 种类型的函数:

  1. HTTP 函数,由简单的 HTTP 请求触发,以及
  2. 后台函数,由 Google Cloud 基础架构中的事件触发,例如 Cloud Firestore 事件。这就是你需要的,所以让我们专注于它。

设置

由于您使用的是 Cloud Firestore,我假设您已经设置了 Firebase 项目。因此,如果您还没有,第一步是安装Firebase CLI并按照其说明在本地设置您的项目。询问时,选择“功能:配置和部署云功能”选项以启用它,并选择“使用现有项目”以选择您的项目。

$ firebase login
$ firebase init

完成设置后,您的目录中基本上将具有以下结构:

firebase.json
.firebaserc
functions/
    index.js
    package.json

现在,在开始编码之前,您应该了解有关 Cloud Firestore 事件的一些信息。其中有 4 个(列表在这里):

  • onCreate:第一次写入文档时触发。
  • onUpdate:当文档已经存在并且任何值发生更改时触发。
  • onDelete:当有数据的文档被删除时触发。

  • onWrite:在触发 onCreate、onUpdate 或 onDelete 时触发。

由于您只需要捕获一个创建事件,因此您将编写一个onCreate事件。

编码

为此,请打开functions/index.js文件并键入以下代码:

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

// this function is triggered by "onCreate" Cloud Firestore events
// the "userId" is a wildcard that represents the id of the document created inside te "users" collection
// it will read the "email" field and insert the "lowercaseEmail" field
exports.onCreateUserInsertEmailLowercase = functions.firestore
    .document('users/{userId}')
    .onCreate((snapshot, context) => {
        // "context" has info about the event
        // reference: https://firebase.google.com/docs/reference/functions/cloud_functions_.eventcontext
        const { userId } = context.params;

        // "snapshot" is a representation of the document that was inserted
        // reference: https://googleapis.dev/nodejs/firestore/latest/DocumentSnapshot.html
        const email = snapshot.get('email');

        console.log(`User ${userId} was inserted, with email ${email}`);

        return null;
    });

正如您可能猜到的,这是一个非常简单的云函数,它只记录文档的 id 及其“电子邮件”字段。所以现在我们转到您问题的第二部分:我们如何编辑这个新创建的文档?这里有两个选项:(1) 更新您刚刚创建的文档和 (2) 更新其他文档,因此我将其分为 2 个部分:

(1) 更新刚刚创建的文档

答案在于“快照”参数。尽管它只是您插入的文档的表示形式,但它内部带有DocumentReference,这是一种具有读取、写入和侦听更改功能的不同类型的对象。让我们使用它的set方法来插入新字段。所以让我们改变我们当前的函数来做到这一点:

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

// this function is triggered by "onCreate" Cloud Firestore events
// the "userId" is a wildcard that represents the id of the document created inside te "users" collection
// it will read the "email" field and insert the "lowercaseEmail" field
exports.onCreateUserInsertEmailLowercase = functions.firestore
    .document('users/{userId}')
    .onCreate((snapshot, context) => {
        // "context" has info about the event
        // reference: https://firebase.google.com/docs/reference/functions/cloud_functions_.eventcontext
        const { userId } = context.params;

        // "snapshot" is a representation of the document that was inserted
        // reference: https://googleapis.dev/nodejs/firestore/latest/DocumentSnapshot.html
        const email = snapshot.get('email');

        console.log(`User ${userId} was inserted, with email ${email}`);

        // converts the email to lowercase
        const lowercaseEmail = email.toLowerCase();

        // get the DocumentReference, with write powers
        const documentReference = snapshot.ref;

        // insert the new field
        // the { merge: true } parameter is so that the whole document isn't overwritten
        // that way, only the new field is added without changing its current content
        return documentReference.set({ lowercaseEmail }, { merge: true });
    });

(2) 从另一个集合中更新一个文档

为此,您需要将firebase-admin添加到您的项目中。它具有所有管理员权限,因此您可以写入项目中的任何 Cloud Firestore 文档。

functions目录中,运行:

$ npm install --save firebase-admin

由于您已经在 Google Cloud 的基础架构中,因此初始化它就像在index.js文件中添加以下几行一样简单:

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

现在您所要做的就是使用 Admin SDK 获取您希望更新的文档的 DocumentReference,并使用它来更新其中一个字段。

对于此示例,我将假设您有一个名为的集合stats,其中包含一个users文档,其中包含一个counter跟踪集合中文档数量的文档users

// this updates the user count whenever a document is created inside the "users" collection
exports.onCreateUpdateUsersCounter = functions.firestore
.document('users/{userId}')
.onCreate(async (snapshot, context) => {
    const statsDocumentReference = admin.firestore().doc('stats/users');

    // a DocumentReference "get" returns a Promise containing a DocumentSnapshot
    // that's why I'm using async/await
    const statsDocumentSnapshot = await statsDocumentReference.get();
    const currentCounter = statsDocumentSnapshot.get('counter');

    // increased counter
    const newCounter = currentCounter + 1;

    // update the "counter" field with the increased value
    return statsDocumentReference.update({ counter: newCounter });
});

就是这样!

部署

但是现在您已经有了编码部分,您如何部署它以使其在您的项目中运行,对吧?让我们再次使用 Firebase CLI 来部署新的 Cloud Functions。

在项目的根目录中,运行:

$ firebase deploy --only functions:onCreateUserInsertEmailLowercase
$ firebase deploy --only functions:onCreateUpdateUsersCounter                                 

这几乎是基础知识,但如果您愿意,可以查看其文档以获取有关部署 Cloud Functions 的更多信息。

调试

好的,对,但我们怎么知道它有效呢?转到https://console.firebase.google.com并尝试一下!插入几个文档,看看奇迹发生了。如果您需要一点调试,请单击左侧的“功能”菜单,您将能够访问您的功能日志。

这对于您的用例场景来说已经差不多了,但是如果您想更深入地了解 Cloud Functions,我真的推荐它的文档。它非常完整,简洁和有条理。我留下了一些链接作为参考,所以你会知道在哪里看。

干杯!


推荐阅读