When I use firebase.firestore()
on client-side, the following function works well and managed to find the document:
With 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);
});
};
On 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);
};
});
But when I tried to create another similar function using firebase-admin
, the following function can't find the document with the same email
argument:
In db.js
With 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;
In Cloud Function:
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
};
};
});
});
Everything works well in the above function without errors except that the doc.exists
always evaluated to false
and always return "User not found."
, why? Anything that I've done wrong in the second version of my code? Thanks!
NOTE: I'm running all emulators: firebase emulators:start
In reference to this post, apparently, the answer is simple: The local Firestore Emulator has NO DATA. This can be easily proven with the following approach based on the exact same code in the question:
Start all emulators except Firestore Emulator:
firebase serve --only hosting
firebase emulators:start --only functions
Now the document is accessible and doc.exists == true
:
Without starting the Firestore Emulator, the code will be forced to access the production server with data. Of course, this is not recommended, especially when you're on Blaze Plan. Hence, as given in the above link, we should setup the test data locally before using Firestore Emulator.
As for the reason why the client-side firebase.firestore()
was able to access the data, this is because the Firestore Emulator runs on port different than the hosting. So the firebase.firestore()
that was being executed in index.js
at the web client side was using localhost:5000
, bypassing the Firestore Emulator and went straight to the production server. To resolve this issue, this Firebase Documentation could be the solution (but not yet tested):
// 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
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With