在 Firestore 模拟器上使用 Firebase-Admin 运行 时找不到 Firestore 文档

Firestore document not found when using Firebase-Admin running on Firestore Emulator

当我在 客户端 上使用 firebase.firestore() 时,以下功能运行良好并设法找到文档:

firebase.firestore()

function getUserProfile(email, returnDoc) {
    var db = firebase.firestore();
    var docRef = db.collection("Users").doc(email);

    docRef.get().then(function (doc) {
        if (doc.exists) {
            returnDoc(undefined, doc);
        } else {
            returnDoc("User not found.", doc);
        }
    }).catch(function (error) {
        returnDoc("Error getting user.", doc);
    });
};

index.js

getUserProfile(user.email, function (err, userProfile) {
   if (!err) {
      $scope.firstName = userProfile.get("FirstName");
      $scope.lastName = userProfile.get("LastName");
      $scope.email = userProfile.get("Email");
      $scope.$apply();
   } else {
      alert(err);
    };
});

但是当我尝试使用 firebase-admin 创建另一个类似函数时,以下函数 无法找到 具有相同 email 参数的文档:

db.jsadmin.firestore()

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

let db = admin.firestore();

function getUserData(email, returnDoc) {
    console.log(`imtp-db.getUserData: ${email}`); // email data is correct and exist in database.

    let docRef = db.collection("Users").doc(email);

    return docRef.get().then(function (doc) {
        console.log(`doc.exists: ${doc.exists}`); // doc.exists: false here.
        if (doc.exists) {
            console.log("Document data:", doc.data());

            return returnDoc(undefined, doc);
        } else {
            return returnDoc("User not found.", doc);
        };
    }).catch(function (error) {
        return returnDoc("Error getting user.", doc);
    });
};

exports.getUserData = getUserData;

在云函数中:

const functions = require('firebase-functions');
const db = require("./middleware/db.js");

exports.getUserProfile = functions.https.onCall((data, context) => {
    var userProfile = undefined;
    console.log(`data.email = ${data.email}`);
    return db.getUserData(data.email, function (err, userDoc) {
        console.log(`exports.getUserProfile.err = ${err}`);
        if (!err) {
            userProfile = userDoc.data();
            return {
                error: err,
                returnData: userProfile
            };
        } else {
            return {
                error: err,
                returnData: userProfile
            };
        };
    });
});

除了 doc.exists 总是评估为 false 并且总是 return "User not found." 之外,上面的函数一切正常,没有错误,为什么?我在第二版代码中做错了什么?谢谢!

注意:我是运行所有模拟器:firebase emulators:start

参照,显然,答案很简单:本地Firestore模拟器没有数据。基于问题中完全相同的代码,可以使用以下方法轻松证明这一点:

启动除 Firestore 模拟器之外的所有模拟器:

  1. firebase serve --only hosting
  2. firebase emulators:start --only functions

现在可以访问文档并且doc.exists == true:

如果不启动 Firestore 模拟器,代码将被迫使用数据访问生产服务器。当然,不推荐这样做,尤其是当您使用 Blaze Plan 时。因此,如 中所述,我们应该在使用 Firestore 模拟器之前在本地设置测试数据。

至于客户端firebase.firestore()能够访问数据的原因,是因为Firestore 模拟器运行在与托管不同的端口上。因此 index.js 网络客户端 中执行的 firebase.firestore() 正在使用 localhost:5000,绕过 Firestore 模拟器并直接进入生产服务器。要解决此问题,Firebase Documentation 可能是解决方案(但尚未测试):

// Initialize your Web app as described in the Get started for Web
// firebaseApp previously initialized using firebase.initializeApp().
var db = firebaseApp.firestore();
if (location.hostname === "localhost") {
  db.settings({
    host: "localhost:8080",
    ssl: false
  });
}

当您使用模拟器时,Firebase 不会从实际的 Firestore 数据库中获取数据。它从 Firestore 模拟器中获取,您可以使用 firebase 模拟器 ui 访问它,以在那里管理数据。 Firestore 模拟器与您实际的 Firestore 数据库不同。

如果你 运行 firebase emulators:start 你可以查看 url 来访问模拟器 ui