【问题标题】:Cannot get FieldValue.increment working in Firestore emulator with Admin SDK无法使用 Admin SDK 在 Firestore 模拟器中获取 FieldValue.increment
【发布时间】:2019-12-05 12:39:16
【问题描述】:

我正在尝试使用 Firestore 触发器在 Firebase Cloud Functions 中进行简单的原子增加/减少。 为了测试这些,我想使用 Firestore 模拟器执行本地测试。

但我总是得到错误 FirebaseError: Function DocumentReference.update() called with invalid data. Unsupported field value: a custom object (found in field myfield)

我的代码就这么简单

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();

export const mytest = functions.firestore.document('my/{doc}').onUpdate(async (change, context) => {
  return perform();
});

export async function perform(): Promise<FirebaseFirestore.WriteResult> {
  const myDocRef = .... // this is a FirebaseFirestore.DocumentReference

  const decrement = admin.firestore.FieldValue.increment(1);
  return myDocRef.update({
    myfield: decrement
  });
}

在我的测试中,我只调用了perform 函数,然后我收到了上述错误。肯定是 FieldValue.increment 导致错误,因为如果我只是在更新调用中输入一个硬编码的数字而不是 decrement,它就可以工作(更新到该硬编码的数字)。

我使用的是 Firebase CLI 7.2.1 和模拟器 1.6.2,根据 Most efficient way to increment a value of everything in Firebasehttps://github.com/firebase/firebase-js-sdk/issues/1799 应该支持模拟器中的 FieldValue.increment

我做错了什么?

【问题讨论】:

    标签: node.js firebase google-cloud-firestore google-cloud-functions firebase-cli


    【解决方案1】:

    你使用的是什么版本的firebase-admin

    根据您的描述,听起来您是直接从 Node.js 脚本调用 perform()。我建议重新设置您的设置,以更接近生产中实际发生的情况:客户端将直接连接到 Firestore,创建一个文档,然后您的函数将被触发。

    这是一个您可以运行的示例:

    const admin = require('firebase-admin');
    const functions = require('firebase-functions');
    admin.initializeApp();
    
    exports.createItem = functions.https.onRequest(async (request, response) => {
      const item = await admin.firestore().collection("items").add({ addedAt: Date.now() });
      response.send(`added ${item.id}\n`);
    });
    
    const counter = admin.firestore().collection("counters").doc("items");
    exports.increment = functions.firestore.document('items/{itemId}').onCreate(async (change, context) => {
      await counter.set({ total: admin.firestore.FieldValue.increment(1) }, { merge: true });
      const current = await counter.get();
      console.log(`incremented counter to ${current.data().total}`);
    });
    

    第一个函数createItem 是一个HTTP 触发器,它将一个文档添加到items/ 集合中。第二个函数是 Firestore 触发器,它会在创建文档时增加 counters/items 文档中的字段。

    当我跑步时

    curl -X POST http://localhost:5001/ryanpbrewster-test/us-central1/createItem
    

    它创建一个文档并发送类似的响应

    added LGOCapHSQtlXKIMEA8Do
    

    这会触发另一个功能,我可以在模拟器日志中看到:

    I function: Beginning execution of "increment"
    >  incremented counter to 6
    
    I function: Finished "increment" in ~1s
    

    【讨论】:

    • 我正在使用firebase-admin 8.3.0。所以我在我的 mocha 测试中使用@firebase/testing,这些测试是针对 firestore 模拟器执行的,不幸的是直到现在它还不支持 firestore 触发器。这就是我将大部分代码从触发器函数提取到一个额外函数 (perform) 的原因,它允许我直接从我的测试中执行这个 perform() 方法,直到 firestore 模拟器支持 firestore 触发器。问题是 - 在生产中我的代码有效,它只是在模拟器中不起作用。
    猜你喜欢
    • 2020-12-26
    • 2020-11-27
    • 2021-03-24
    • 2021-10-16
    • 2020-10-21
    • 2021-06-21
    • 1970-01-01
    • 2020-02-10
    相关资源
    最近更新 更多