Using Firebase Cloud Functions to fan out data

Viewed 163

I'm extremely new to using Firebase cloud functions, and I am struggling to find the error in my code. It is supposed to trigger on a firestore write and then copy that document into all of the user's feeds who follow that user who posted.

My current code is below:

exports.fanOutPosts = functions.firestore
    .document('posts/{postId}')
    .onCreate((snap, context) => {
        var db = admin.firestore();
        const post = snap.data();
        const userID = post['author'];
        const postCollectionRef = db.collection('friends').document(userID).collection('followers');

            return postCollectionRef.get()
                .then(querySnapshot => {

                    if (querySnapshot.empty) {
                        return null;
                    } else {
                        const promises = []

                        querySnapshot.forEach(doc => {
                            promises.push(db.collection('feeds').document(doc.key).collection('posts').document(post.key).update(data));
                        });

                        return Promise.all(promises);
                    }
            });
});

So this successfully deploys to Firebase, but it receives this error when a document is created:

TypeError: db.collection(...).document is not a function
    at exports.fanOutPosts.functions.firestore.document.onCreate (/workspace/index.js:22:60)

Line 22 is const postCollectionRef = db.collection('friends').document(userID).collection('followers'); I am unsure why this line is causing errors with the .get, but if anyone could point me in the right direction it would be much appreciated!

2 Answers

Given that this is the nodejs API, you'll want to use doc() instead of document(). Other languages might use document().

I found this info via the Admin SDK on CollectionReference https://googleapis.dev/nodejs/firestore/latest/CollectionReference.html

According to the reference, the collection should be defined as the following:

const postCollectionRef = db.collection(`friends/${userId}/followers`);

Using template literals will allow you to dynamically add variables into the collection ref.

I would also take a look into the else logic to use template literals within your return statement.

Related