I have a cloud function which attempts to add a "follower" to a users followers collection which will store this data:
id username timestamp
The username property isn't available so I need to get the user doc from firestore and store the username property value so I can add it when I create the new document in the users->following collection.
I've tried several different ways of getting the document but no matter what I try, I keep bumping into some promise related errors.
The current iteration of my function looks like this:
exports.onFollowCreate = functions.firestore
.document('users/{user_id}/{following}/{id}')
.onCreate((snap, context) => {
const newValue = snap.data();
const db = admin.firestore();
db.collection("users")
.doc(context.params.user_id)
.update({followingCount: admin.firestore.FieldValue.increment(1)})
.catch((er) => {
console.log(er);
});
const userDocRef = admin.firestore().collection("users").doc(context.params.id);
userDocRef.get().then((snapshot) => {
if (snapshot.docs.length > 0) {
snapshot.docs.foreach((doc) => {
const username = doc.data();
db.collection("users")
.doc(newValue.id)
.collection("followers")
.doc(context.params.user_id)
.set({
id: context.params.user_id,
username: username,
timeStamp: new Date(),
})
.catch((er) => console.log(er));
});
} else {
console.log("Error: No documents found");
}
});
});
Showing the following in the google cloud functions logs explorer:
Function execution started
Function returned undefined, expected Promise or value
Function execution took 3179 ms. Finished with status: ok
Exception from a finished function: TypeError: Cannot read properties of undefined (reading 'length')
CodePudding user response:
The reason you got error is because in the line:
const userDocRef = admin.firestore().collection("users").doc(context.params.id);
The userDocRef
will get exactly one doc. Instead of reaching it in the docs
, you should check the document existence by snapshot.exists()
. The docs
field doesn't exist here, so snapshot.docs.length
is throwing an error.
Besides of that, the code has multiple places to change:
- Despite we don't need to use
foreach
at all, you don't need to wrap a pure foreach loop in a if statement. - If my understanding is right, the
username
is a string, but you will get a json file fromsnapshot.data()
. Consider change the code toconst username = doc.data()["username"];