Skip to content
Advertisement

Saving data to Firestore from Google Cloud Function

I have a function I’ved deployed and scheduled to run every morning into my Google Cloud Functions. It says it runs successfuly and I even see some of the console logs I haven’t taken out yet, but when I look at my firestore collection the data isn’t updated. If I run this same function locally in my Visually Studio code using node, then it works perfectly. Just trying to figure out what I’m missing here. Here is the function, it’s not very long.

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const request = require('request');
const cheerio = require('cheerio');
const cheerioTableparser = require('cheerio-tableparser');
const requestP = require('request-promise');

exports.scrape = functions.pubsub.schedule('0 4 * * *')
    .onRun(async (context) => {

        //Service Account for access
        var serviceAccount = {
            "type": "service_account",
            "project_id": "PROJECT-ID",
            "private_key_id": "PRIVATE-KEY-ID",
            "private_key": "PRIVATE KEY",
            "client_email": "hoopfire-admin@hoopfire-api.iam.gserviceaccount.com",
            "client_id": "CLIENT-ID",
            "auth_uri": "https://accounts.google.com/o/oauth2/auth",
            "token_uri": "https://accounts.google.com/o/oauth2/token",
            "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
            "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/hoopfire-admin%40hoopfire-api.iam.gserviceaccount.com"
        }

        //Init app
        // admin.initializeApp({
        //     credential: admin.credential.cert(serviceAccount)
        // });
        if (admin.apps.length === 0) {
            admin.initializeApp();
        }

        var db = admin.firestore();

        //-------------------------------------------------------- NBA ------------------------------------------------------

        //Make a request to KenPom url for HMTL
        request('https://www.basketball-reference.com/leagues/NBA_2023.html#advanced-team', async function (error, response, html) {
            if (!error && response.statusCode == 200) {
                //Load HTML into Cheerio
                var $ = cheerio.load(html);

                //Load cheerio htl, into cheerioTableParser plugin
                cheerioTableparser($);

                var jsonData = [];
                var data = $("#advanced-team").parsetable(true, true, true);

                //Loop through matrix and created array of objects with associated properties
                for (var i = 1; i < data[0].length; i++) {
                    var team = {
                        "rank": data[0][i],
                        "team": data[1][i],
                        "wins": data[3][i],
                        "losses": data[4][i],
                        "oRtg": data[10][i],
                        "dRtg": data[11][i],
                        "pace": data[13][i]
                    }
                    jsonData.push(team);
                    console.log(team.team);
                }
                //Remove initial elment bc its filled with the titles of the columns
                jsonData.splice(0, 1);

                var _datarwt = [];
                // //Loop through cleaned data and add to the FireStore
                for (var i = 0; i < jsonData.length; i++) {
                    // var ref = db.collection('nba-teams').doc(jsonData[i].team);
                    // ref.set(jsonData[i]);
                    _datarwt.push(db.collection('nba-teams').doc(jsonData[i].team).set(jsonData[i]));
                }

                const _dataloaded = await Promise.all(_datarwt)
                  .then(() => {
                    response.send('NBA COMPLETE');
                  })
                  .catch((err) => {
                    console.log(err);
                  });
            }
        });
    })

I’ve removed the account access details, so those generic values aren’t the issue, just FYI.

Advertisement

Answer

try {
            const res = await axios.get('https://www.basketball-reference.com/leagues/NBA_2023.html#advanced-team', config)

            //Load HTML into Cheerio
            var $ = cheerio.load(res.data);

            //Load cheerio htl, into cheerioTableParser plugin
            cheerioTableparser($);

            var jsonData = [];
            var data = $("#advanced-team").parsetable(true, true, true);

            //Loop through matrix and created array of objects with associated properties
            for (var i = 1; i < data[0].length; i++) {
                var team = {
                    "rank": data[0][i],
                    "team": data[1][i],
                    "wins": data[3][i],
                    "losses": data[4][i],
                    "oRtg": data[10][i],
                    "dRtg": data[11][i],
                    "pace": data[13][i]
                }
                jsonData.push(team);
                // console.log(team.team);
            }
            //Remove initial elment bc its filled with the titles of the columns
            jsonData.splice(0, 1);

            const _datarwt = [];
            // //Loop through cleaned data and add to the FireStore
            for (var i = 0; i < jsonData.length; i++) {
                _datarwt.push(db.collection('nba-teams').doc(jsonData[i].team).set(jsonData[i]));
            }

            const _dataloaded = await Promise.all(_datarwt)
                .then(() => {
                    console.log('NBA COMPLETE')
                })
                .catch((err) => {
                    console.log(err);
                });
        } catch (err) {
            // Handle Error Here
            console.error(err);
        }

I ended up switching to axios so everything is promise and async/await based and its working now.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement