在 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.js
和admin.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 模拟器之外的所有模拟器:
firebase serve --only hosting
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
当我在 客户端 上使用 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.js
和admin.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 模拟器之外的所有模拟器:
firebase serve --only hosting
firebase emulators:start --only functions
现在可以访问文档并且doc.exists == true
:
如果不启动 Firestore 模拟器,代码将被迫使用数据访问生产服务器。当然,不推荐这样做,尤其是当您使用 Blaze Plan 时。因此,如
至于客户端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