云功能/Firestore。当字段位于不同文档中时如何触发

Posted

技术标签:

【中文标题】云功能/Firestore。当字段位于不同文档中时如何触发【英文标题】:Cloud functions/Firestore. How to trigger when the fields stay in different documents 【发布时间】:2021-08-18 07:05:09 【问题描述】:

如上图所示,我的 device-configs 集合中有两个文档。第一个:设备配置/车库。我将其称为 document_1。第二个:device-configs/garagem2。我将其称为 document_2。

当garagestate (document_2) 字段为false 时,该字段(type map) value.openPercent of document_1 的值必须为100。当字段garagestate (document_2) 为true 时,该值document_1 的字段 value.openPercent 必须为 0 说明:在项目内可能会在其他客户端项目中手动更改 document_2 的值。所以我需要这个云函数 trigger/onUpdate。

下面我介绍我目前拥有的代码和问题。欢迎任何帮助:

const functions = require("firebase-functions");
const  firestore  = require("./admin");

exports.updateGarage = functions.firestore
  .document("device-configs/garagem2")
  .onUpdate((change, context) => 
    // Get an object representing the document
    // e.g. 'name': 'Marie', 'age': 66
    const newValue = change.after.data();

    const garagestatev = newValue.garagestate;

      firestore
      .doc(`device-configs/garagem`)
      .get()
      .then((areaSnapshot) => 

        const targetDoc = areaSnapshot.data().value.openPercent

            if (garagestatev) 
                console.log("garagestate is true = targetDodc=k"+targetDoc);
      
                if (targetDoc == 100) 
                  console.log("vou mandar 0");
      
                  firestore
                    .collection("device-confings")
                    .document("garagem")
                    .update(mapOf("value.openPercent", to, 0));
                

             else if (!garagestatev) 
                
                console.log("garagestate is false = targetDodc=k"+targetDoc);

                if (targetDoc == 0) 
                  console.log("vou mandar 100");
                  firestore
                    .collection("device-confings")
                    .document("garagem")
                    .update(mapOf("value.openPercent", to, 100));
                
              
      );
  );


firebase functions:log --project control-my-lighs
2021-05-30T18:04:14.031Z ? updateGarage:     at processTicksAndRejections (internal/process/task_queues.js:97:5)
2021-05-30T18:04:15.107Z E updateGarage: Error: Process exited with code 16
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:275:22)
    at process.emit (events.js:314:20)
    at process.EventEmitter.emit (domain.js:483:12)
    at process.exit (internal/process/per_thread.js:168:15)
    at Object.sendCrashResponse (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/logger.js:37:9)
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:271:22)
    at process.emit (events.js:314:20)
    at process.EventEmitter.emit (domain.js:483:12)
    at processPromiseRejections (internal/process/promises.js:209:33)
    at processTicksAndRejections (internal/process/task_queues.js:98:32)
2021-05-30T18:04:25.644468172Z N updateGarage: 
2021-05-30T18:14:28.870453Z I : 
2021-05-30T18:14:29.170182Z I : 
2021-05-30T18:14:30.371944Z N updateGarage: 
2021-05-30T18:15:36.776727Z N updateGarage: 
2021-05-30T18:28:51.856151587Z D updateGarage: Function execution started
2021-05-30T18:28:51.911Z W updateGarage: Function returned undefined, expected Promise or value
2021-05-30T18:28:51.925301683Z D updateGarage: Function execution took 70 ms, finished with status: 'ok'
2021-05-30T18:32:16.601Z ? updateGarage: Unhandled rejection
2021-05-30T18:32:16.601Z ? updateGarage: TypeError: Cannot read property 'doc' of undefined
2021-05-30T18:32:16.601Z ? updateGarage:     at /workspace/index.js:20:9
2021-05-30T18:32:16.601Z ? updateGarage:     at processTicksAndRejections (internal/process/task_queues.js:97:5)
2021-05-30T18:32:17.970Z E updateGarage: Error: Process exited with code 16
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:275:22)
    at process.emit (events.js:314:20)
    at process.EventEmitter.emit (domain.js:483:12)
    at process.exit (internal/process/per_thread.js:168:15)
    at Object.sendCrashResponse (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/logger.js:37:9)
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:271:22)
    at process.emit (events.js:314:20)
    at process.EventEmitter.emit (domain.js:483:12)
    at processPromiseRejections (internal/process/promises.js:209:33)
    at processTicksAndRejections (internal/process/task_queues.js:98:32)
2021-05-30T18:41:52.632854Z I : 
2021-05-30T18:41:52.986410Z I : 
2021-05-30T18:41:54.241235Z N updateGarage: 
2021-05-30T18:43:05.140969Z N updateGarage: 
2021-05-30T19:25:19.353311Z I : 
2021-05-30T19:25:19.700197Z I : 
2021-05-30T19:25:20.976786Z N updateGarage: 
2021-05-30T19:26:25.017448Z N updateGarage: 
2021-05-30T19:28:08.685592Z I : 
2021-05-30T19:28:08.950658Z I : 
2021-05-30T19:28:10.193327Z N updateGarage: 
2021-05-30T19:29:11.637770Z N updateGarage: 
2021-05-30T19:34:04.532315Z I : 
2021-05-30T19:34:04.876667Z I : 
2021-05-30T19:34:06.052541Z N updateGarage: 
2021-05-30T19:35:13.534912Z N updateGarage: 
2021-05-30T19:35:43.595986Z I : 
2021-05-30T19:35:43.852178Z I : 
2021-05-30T19:35:45.180154Z N updateGarage: 
2021-05-30T19:36:55.044093Z N updateGarage:

https://github.com/neuberfran/updateGarage/blob/main/functions/index.js

【问题讨论】:

【参考方案1】:

每个云函数都应该返回一个 Promise 或一个值。在您的情况下,您应该返回从数据库中获取值的 Promise,然后更新另一个文档。

另外,你不应该嵌套 Promise。推荐使用Promise Chaining。

更新: 在添加 Promise 链接并在云函数中返回 Promise 之后,我添加了代码。 mapOf 也不是必需的,您可以直接更新对象。

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
    exports.updateGarage = functions.firestore
        .document("device-configs/garagem2")
        .onUpdate((change, context) => 
    
            //Get the latest value after update
            const newValue = change.after.data();
    
            //Current state of garage
            const garagestatev = newValue.garagestate;
    
            return admin.firestore().doc(`device-configs/garagem`).get()
                .then((areaSnapshot) => areaSnapshot.data().value.openPercent)
                .then(targetDoc => 
    
                    //Target doc has openPercent of other document ('garagem')
                    if (garagestatev) 
                        console.log("garagestate is true = targetDodc=k" + targetDoc);
    
                        if (targetDoc === 100) 
                            console.log("vou mandar 0");
                            //Returning Promise inside of .then() block 
                            return admin.firestore()
                                .collection("device-configs")
                                .doc("garagem")
                                .update( "value.openPercent": 0 );
                        
    
                     else 
    
                        console.log("garagestate is false = targetDodc=k" + targetDoc);
    
                        if (targetDoc === 0) 
                            console.log("vou mandar 100");
                            //Returning Promise inside of .then() block 
                            return admin.firestore()
                                .collection("device-configs")
                                .doc("garagem")
                                .update( "value.openPercent": 100 );
                        
                    
                )
    
        );

如果不能保证,您还可以添加对文档是否存在的检查。

【讨论】:

我需要在我的代码(上面)中具体更改哪些内容? 我已经用代码 sn-p 编辑了答案。 Tks。但还没有解决。该函数编译并在控制台上显示正常。但我仍然有以下问题: updateGarage: TypeError: firestore.collection(...).document is not a function gist.github.com/neuberfran/… drive.google.com/file/d/1NoB2lGs18iT3iyqfZd929Vv51Uq7_aq5/… 在您的答案中将 (2x) 设备配置替换为设备配置(正确)。但问题是:TypeError: firestore.collection(...).document is not a function 继续 抱歉,我没有检查导入。我已经编辑了答案以反映需要作为函数调用的导入 (admin.firestore())。您还必须使用admin.initializeApp(); 初始化应用程序。希望这能解决您的问题。

以上是关于云功能/Firestore。当字段位于不同文档中时如何触发的主要内容,如果未能解决你的问题,请参考以下文章

Firebase文档审阅,还有一些关于选择Firestore和Cloud Functions位置的问题

如何从云功能中移动 Firestore 文档?

当标识字段位于两个单独的列中时,如何检索该特定记录的最新出现? [关闭]

Firestore 将值添加到数组字段

当文本字段位于 uitableviewcell 中时,不调用 touchesBegan

使用云功能更新 Firestore 文档