11
votes

Within my Google Firebase Firstore database I would like to gather aggregative data such as how many documents a collection has. Since Firestore does not provide aggregative queries I'm attempting to write a cloud function that will increment a field every time a document is added to the database which will contain the number of documents a collection has.

The problem I'm having is I cannot for the life of me figure out how to grab documents from Firestore within a cloud function using nodejs.

Here's what I'm doing:

At the top of my index.js file I configure the admin SDK and what have you like this:

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

Then for my cloud function I do this:

exports.createPost = functions.firestore
  .document('posts/{post_id}')
  .onCreate(event => {

    // Get the post object
    var post = event.data.data();

    var senderID = post["sender_id"]; // This is not null

    // Access to user's document and the main ledger document
    const userDocRef = admin.database().ref('/users').orderByChild("user_id").equalTo(senderID).once('value')
    const ledgerDocRef = admin.database().ref('/posts/ledger').once('value');

    return Promise.all([userDocRef, ledgerDocRef]).then(snapshot => {

        const user = snapshot[0].val();
        const ledger = snapshot[1].val();

        console.log("user => "+user); // Logs: user => null
        console.log("ledger => "+ledger); // Logs: ledger => null

        const userPostCount = user["user_name"];
        const globalPostCount = ledger["global_post_count"] + 1;

        const userUpdate = user.update({"post_count" : userPostCount});
        const ledgerUpdate = ledger.update({"global_post_count" : globalPostCount});

        return Promise.all([userUpdate, ledgerUpdate]);
    });
});

I end up with the error:

TypeError: Cannot read property 'global_post_count' of null at Promise.all.then.snapshot

Which I figure means something is wrong with my query but I don't know what. Both the users and posts are root level collections.

Im also getting a warning that says:

Billing account not configured. External network is not accessible and quotas are severely limited.

From what I've read online, I don't think that effects it but I thought it was worth noting.

Please help.

1

1 Answers

18
votes

Looks like you've written a Firestore trigger, but are then reaching into Realtime Database for queries:

const userDocRef = admin.database().ref('/users').orderByChild("user_id").equalTo(senderID).once('value')
const ledgerDocRef = admin.database().ref('/posts/ledger').once('value');

If your RTDB is empty, these queries will also end up empty.

To query Firestore, you need to be using admin.firestore() instead of admin.database(). Firestore has a mostly different API (via the Cloud SDK I just linked) than RTDB, but they are similar in some ways.