Avatar of Bruce Gust
Bruce Gust
Flag for United States of America asked on

Profile.save is not a function. What am I doing wrong?

Here's my code in full:

require("dotenv").config();
const { validationResult } = require("express-validator/check");
const mongoose = require("mongoose");
const Profile = require("../models/profile");
const ClientId = process.env.CLIENTID;
const Secret = process.env.SECRET;
const Callback = process.env.CALLBACK;

//this is the empID you're getting from AHA
const empID = 7747;

//get today's date
let date_ob = new Date();

// current date
// adjust 0 before single digit date
let date = ("0" + date_ob.getDate()).slice(-2);

// current month
let month = ("0" + (date_ob.getMonth() + 1)).slice(-2);

// current year
let year = date_ob.getFullYear();

// prints date in YYYY-MM-DD format
let today = year + "-" + month + "-" + date;

const FitbitApiClient = require("fitbit-node");
const client = new FitbitApiClient({
  clientId: ClientId, //client_id
  clientSecret: Secret, //client secret
  apiVersion: "1.2" // 1.2 is the default
});

exports.getCallback = (req, res, next) => {
  const yesterday_raw = new Date(new Date().setDate(new Date().getDate() - 1));
  const yesterday = yesterday_raw.toISOString().slice(0, 10);

  client.getAccessToken(req.query.code, Callback).then(result => {
    var requests = [
      client.get("/profile.json", result.access_token), //0
      client.get("/activities/date/today.json", result.access_token), //1
      //client.get("/sleep/date/" + yesterday + ".json", result.access_token), //2
      client.get("/sleep/date/today.json", result.access_token), //2
      //client.get("/sleep/date/2019-11-05.json", result.access_token), //2
      client.get(
        "/foods/log/caloriesIn/date/today/1d.json",
        result.access_token
      ), //dailly intake of calories 3
      client.get("/foods/log/water/date/today.json", result.access_token), // 4 this works!
      client.get("/activities/heart/date/today/1d.json", result.access_token), //5
      client.get("/body/log/weight/goal.json", result.access_token, undefined, {
        "Accept-Language": "en_US"
      }), //6
      client.get("/activities/date/" + yesterday + ".json", result.access_token) //7
    ];
    Promise.all(requests)
      .then(data => {
        //profile info
        const firstName = data[0][0].user.firstName; //0
        const lastName = data[0][0].user.lastName; //0
        const dateOfBirth = data[0][0].user.dateOfBirth; //0
        const gender = data[0][0].user.gender; //0

        //calorie goals - to be burned including BMR
        const calories_goal = JSON.stringify(data[1][0]["goals"].calories); //1 calorie goal
        const massive_total = JSON.stringify(data[1][0].summary.calories.total); //1 big calorie total
        const BMR = JSON.stringify(data[1][0].summary.calories.bmr); //1 - BMR
        const calories_burned = massive_total - BMR;

        //sleep
        const slumber = JSON.stringify(
          data[2][0].summary.totalMinutesAsleep / 60
        ); //2 total sleep hours
        const sleep = JSON.stringify(Math.round(slumber * 10) / 10);

        const rem_sleep = data[2][0]["sleep"].length
          ? data[2][0]["summary"].stages.rem
          : 0; //minutes in deep REM sleep

        //nutrition
        const eating = JSON.stringify(
          data[3][0]["foods-log-caloriesIn"][0].value
        ); //3
        const caloriesIn = eating.replace(/\"/g, "");

        //water
        const water = JSON.stringify(data[4][0].summary.water);

        //heart rate
        const rhr = JSON.stringify(
          data[5][0]["activities-heart"][0].value.restingHeartRate
        );

        //body weight goal
        //res.setHeader('Accept-Language', 'en_US')
        const startWeight = JSON.stringify(data[6][0].goal.startWeight);
        const targetWeight = JSON.stringify(data[6][0].goal.weight);
        //res.send(targetWeight);

        //steps
        const totalStepsYesterday = JSON.stringify(data[7][0].summary.steps);
        const totalStepsSoFar = JSON.stringify(data[1][0].summary.steps);

        //console.log("here's where you're putting our INSERT code");

        Profile.find({ empID: empID, todaysDate: today }).then(profile => {
          if (profile) {
            //console.log("someone's here");
            profile.empID = empID;
            profile.todaysDate = today;
            profile.firstName = firstName;
            profile.lastName = lastName;
            profile.dateOfBirth = dateOfBirth;
            profile.gender = gender;
            profile.bodyStartWeight = startWeight;
            profile.bodyTargetWeight = targetWeight;
            profile.calorieGoal = calories_goal;
            profile.caloriesConsumed = caloriesIn;
            profile.caloriesBurned = calories_burned;
            profile.waterConsumpution = water;
            profile.BMR = BMR;
            profile.totalHoursSlept = sleep;
            profile.REM = rem_sleep;
            profile.RHR = rhr;
            profile.totalStepsYesterday = totalStepsYesterday;
            profile.totalStepsSoFar = totalStepsSoFar;
            return Profile.save()
              .then(result => {
                console.log("updated row");
              })
              .catch(err => {
                const error = new Error(err);
                error.httpStatusCode = 500;
                return next(error);
              });
          } else {
            const profile = new Profile({
              empID: empID,
              todaysDate: today,
              firstName: firstName,
              lastName: lastName,
              dateOfBirth: dateOfBirth,
              gender: gender,
              bodyStartWeight: startWeight,
              bodyTargetWeight: targetWeight,
              calorieGoal: calories_goal,
              caloriesConsumed: caloriesIn,
              caloriesBurned: calories_burned,
              waterConsumpution: water,
              BMR: BMR,
              totalHoursSlept: sleep,
              REM: rem_sleep,
              RHR: rhr,
              totalStepsYesterday: totalStepsYesterday,
              totalStepsSoFar: totalStepsSoFar
            });
            profile
              .save()
              .then(result => {
                console.log("got it done");
                res.redirect("/success");
              })
              .catch(err => {
                const error = new Error(err);
                error.httpStatusCode = 500;
                return next(error);
              });
          }
        });
      }) // end of update or insert
      .catch(err => {
        const error = new Error(err);
        error.httpStatusCode = 500;
        return next(error);
      });
  });
};

exports.getSuccess = (req, res, next) => {
  console.log("hello");
  res.status(200).render("authorize/success", {
    pageTitle: "Success",
    path: "/success"
  });
};

Open in new window


What you're looking at is good to except for the one piece of functionality that you see on line #105.

I'm trying to differentiate between adding a row or updating an already existing row.

I'm new to Node, so I'm trying to mimic the Udemy tutorial I'm going through, but I'm missing something because I keep getting an error that says, "UnhandledPromiseRejectionWarning: TypeError: Profile.save is not a function."

For the sake of brevity, that's going to be right here:

Profile.find({ empID: empID, todaysDate: today }).then(profile => {
          if (profile) {
            //console.log("someone's here");
            profile.empID = empID;
            profile.todaysDate = today;
            profile.firstName = firstName;
            profile.lastName = lastName;
            profile.dateOfBirth = dateOfBirth;
            profile.gender = gender;
            profile.bodyStartWeight = startWeight;
            profile.bodyTargetWeight = targetWeight;
            profile.calorieGoal = calories_goal;
            profile.caloriesConsumed = caloriesIn;
            profile.caloriesBurned = calories_burned;
            profile.waterConsumpution = water;
            profile.BMR = BMR;
            profile.totalHoursSlept = sleep;
            profile.REM = rem_sleep;
            profile.RHR = rhr;
            profile.totalStepsYesterday = totalStepsYesterday;
            profile.totalStepsSoFar = totalStepsSoFar;
            return Profile.save()
              .then(result => {
                console.log("updated row");
              })

Open in new window


That's lines 108 - 131.

What am I doing wrong?
Node.jsJavaScript

Avatar of undefined
Last Comment
Bruce Gust

8/22/2022 - Mon
leakim971

profile.save()

The << P >> should be lowercase
Bruce Gust

ASKER
I get the same error...
leakim971

yes  this is not a Profile but the json data itself
do what you did line 138 to 157 :

Profile.find({ empID: empID, todaysDate: today }).then(profile => {
    if (profile) {

        const new_profile = new Profile({
            empID: profile.empID,
            todaysDate: profile.todaysDate,
            firstName: profile.firstName,
            lastName: profile.lastName,
            dateOfBirth: profile.dateOfBirth,
            gender: profile.gender,
            bodyStartWeight: profile.startWeight,
            bodyTargetWeight:profile.targetWeight,
            calorieGoal: profile.calories_goal,
            caloriesConsumed: profile.caloriesIn,
            caloriesBurned: profile.calories_burned,
            waterConsumpution: profile.water,
            BMR: profile.BMR,
            totalHoursSlept: profile.sleep,
            REM: profile.rem_sleep,
            RHR: profile.rhr,
            totalStepsYesterday: profile.totalStepsYesterday,
            totalStepsSoFar: profile.totalStepsSoFar
        });
        new_profile.save()

Open in new window

Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
Bruce Gust

ASKER
Leak, this is going to work! But, I wanted to run something by you because it feels kind of clunky.

At first, I couldn't get it to work. Then I did a console log of "person" like what you see below.

 Profile.find({ empID: empID, todaysDate: today }).then(person => {
          if (person) {
            [b]console.log(person[0].empID);[/b]
            const profile = new Profile({
              empID: person.empID,
              todaysDate: person.today,
              firstName: person.firstName,
              lastName: person.lastName,
              dateOfBirth: person.dateOfBirth,
              gender: person.gender,
              bodyStartWeight: person.startWeight,
              bodyTargetWeight: person.targetWeight,
              calorieGoal: person.calories_goal,
              caloriesConsumed: person.caloriesIn,
              caloriesBurned: person.calories_burned,
              waterConsumpution: person.water,
              BMR: person.BMR,
              totalHoursSlept: person.sleep,
              REM: person.rem_sleep,
              RHR: person.rhr,
              totalStepsYesterday: person.totalStepsYesterday,
              totalStepsSoFar: person.totalStepsSoFar
            });
            profile
              .save()
              .then(result => {
                console.log("got it done");
                res.redirect("/success");
              })
              .catch(err => {
                const error = new Error(err);
                error.httpStatusCode = 500;
                return next(error);
              });
          }

Open in new window


You see the line I've got in bold? Keep that in mind.

Initially I couldn't get it to work and then I console-logged out "person" and this is what I got:

[ { _id: 5dcd9411a80284295ce8be11,
    empID: 7747,
    todaysDate: '2019-11-14',
    firstName: 'Bruce',
    lastName: 'Gust',
    dateOfBirth: '1963-08-26',
    gender: 'MALE',
    bodyStartWeight: 180,
    bodyTargetWeight: 170,
    calorieGoal: 2692,
    caloriesConsumed: 0,
    caloriesBurned: 481,
    BMR: 809,
    totalHoursSlept: 5.3,
    REM: 60,
    RHR: 53,
    totalStepsYesterday: 17127,
    totalStepsSoFar: 4990,
    __v: 0 } ]

Open in new window


It wasn't until I did person[0].empID etc that I could retrieve any of the values.

That feels kind of clunky. Am I doing something wrong?
leakim971

No, it's normal behavior, find return array of objects
You may want to use findOne which return one object
Bruce Gust

ASKER
Actually, Leak...

It's adding another record. IT's not updating what's already there. So I'm not getting any errors but I need to update what's there and not add another record when there's a match between the empID and the date.

Where am I blowing it?
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
leakim971

Where am I blowing it?

The _id is not set

Check this too :

Profile.findOne({ empID: empID, todaysDate: today }).then(profile => {
    if(profile) {
        const new_profile = {
            todaysDate: profile.todaysDate,
            firstName: profile.firstName,
            lastName: profile.lastName,
            dateOfBirth: profile.dateOfBirth,
            gender: profile.gender,
            bodyStartWeight: profile.startWeight,
            bodyTargetWeight: profile.targetWeight,
            calorieGoal: profile.calories_goal,
            caloriesConsumed: profile.caloriesIn,
            caloriesBurned: profile.calories_burned,
            waterConsumpution: profile.water,
            BMR: profile.BMR,
            totalHoursSlept: profile.sleep,
            REM: profile.rem_sleep,
            RHR: profile.rhr,
            totalStepsYesterday: profile.totalStepsYesterday,
            totalStepsSoFar: profile.totalStepsSoFar
        };
        Profile.replaceOne({ _id : profile._id }, new_profile);
    }
});

Open in new window

Bruce Gust

ASKER
Leak, we're getting closer but it's still not working. And the thing is, it's inconsistent.

First thing I noticed is that I lost some data. I shot in the dark and I was able to solve that dilemma by doing this:

const new_profile = {
              todaysDate: today,
              firstName: firstName,
              lastName: lastName,
              dateOfBirth: dateOfBirth,
              gender: gender,
              bodyStartWeight: startWeight,
              bodyTargetWeight: targetWeight,
              calorieGoal: calories_goal,
              caloriesConsumed: caloriesIn,
              caloriesBurned: calories_burned,
              waterConsumpution: water,
              BMR: BMR,
              totalHoursSlept: sleep,
              REM: rem_sleep,
              RHR: rhr,
              totalStepsYesterday: totalStepsYesterday,
              totalStepsSoFar: totalStepsSoFar
            };

            return Profile.replaceOne({ _id: profile._id }, new_profile)

Open in new window


But after that got ironed out, I noticed that it would still add another row even when it was supposed to be updating what was already there.

Here's the whole thing:

require("dotenv").config();
const { validationResult } = require("express-validator/check");
const mongoose = require("mongoose");
const Profile = require("../models/profile");
const ClientId = process.env.CLIENTID;
const Secret = process.env.SECRET;
const Callback = process.env.CALLBACK;

//this is the empID you're getting from AHA
const empID = 7747;

//get today's date
let date_ob = new Date();

// current date
// adjust 0 before single digit date
let date = ("0" + date_ob.getDate()).slice(-2);

// current month
let month = ("0" + (date_ob.getMonth() + 1)).slice(-2);

// current year
let year = date_ob.getFullYear();

// prints date in YYYY-MM-DD format
let today = year + "-" + month + "-" + date;

const FitbitApiClient = require("fitbit-node");
const client = new FitbitApiClient({
  clientId: ClientId, //client_id
  clientSecret: Secret, //client secret
  apiVersion: "1.2" // 1.2 is the default
});

exports.getCallback = (req, res, next) => {
  const yesterday_raw = new Date(new Date().setDate(new Date().getDate() - 1));
  const yesterday = yesterday_raw.toISOString().slice(0, 10);

  client.getAccessToken(req.query.code, Callback).then(result => {
    var requests = [
      client.get("/profile.json", result.access_token), //0
      client.get("/activities/date/today.json", result.access_token), //1
      //client.get("/sleep/date/" + yesterday + ".json", result.access_token), //2
      client.get("/sleep/date/today.json", result.access_token), //2
      //client.get("/sleep/date/2019-11-05.json", result.access_token), //2
      client.get(
        "/foods/log/caloriesIn/date/today/1d.json",
        result.access_token
      ), //dailly intake of calories 3
      client.get("/foods/log/water/date/today.json", result.access_token), // 4 this works!
      client.get("/activities/heart/date/today/1d.json", result.access_token), //5
      client.get("/body/log/weight/goal.json", result.access_token, undefined, {
        "Accept-Language": "en_US"
      }), //6
      client.get("/activities/date/" + yesterday + ".json", result.access_token) //7
    ];
    Promise.all(requests)
      .then(data => {
        //profile info
        const firstName = data[0][0].user.firstName; //0
        const lastName = data[0][0].user.lastName; //0
        const dateOfBirth = data[0][0].user.dateOfBirth; //0
        const gender = data[0][0].user.gender; //0

        //calorie goals - to be burned including BMR
        const calories_goal = JSON.stringify(data[1][0]["goals"].calories); //1 calorie goal
        const massive_total = JSON.stringify(data[1][0].summary.calories.total); //1 big calorie total
        const BMR = JSON.stringify(data[1][0].summary.calories.bmr); //1 - BMR
        const calories_burned = massive_total - BMR;

        //sleep
        const slumber = JSON.stringify(
          data[2][0].summary.totalMinutesAsleep / 60
        ); //2 total sleep hours
        const sleep = JSON.stringify(Math.round(slumber * 10) / 10);

        const rem_sleep = data[2][0]["sleep"].length
          ? data[2][0]["summary"].stages.rem
          : 0; //minutes in deep REM sleep

        //nutrition
        const eating = JSON.stringify(
          data[3][0]["foods-log-caloriesIn"][0].value
        ); //3
        const caloriesIn = eating.replace(/\"/g, "");

        //water
        const water = JSON.stringify(data[4][0].summary.water);

        //heart rate
        const rhr = JSON.stringify(
          data[5][0]["activities-heart"][0].value.restingHeartRate
        );

        //body weight goal
        //res.setHeader('Accept-Language', 'en_US')
        const startWeight = JSON.stringify(data[6][0].goal.startWeight);
        const targetWeight = JSON.stringify(data[6][0].goal.weight);
        //res.send(targetWeight);

        //steps
        const totalStepsYesterday = JSON.stringify(data[7][0].summary.steps);
        const totalStepsSoFar = JSON.stringify(data[1][0].summary.steps);

        //console.log("here's where you're putting our INSERT code");

        Profile.findOne({ empID: empID, todaysDate: today }).then(profile => {
          if (profile) {
            // console.log(person[0][0].empID);

            const new_profile = {
              todaysDate: today,
              firstName: firstName,
              lastName: lastName,
              dateOfBirth: dateOfBirth,
              gender: gender,
              bodyStartWeight: startWeight,
              bodyTargetWeight: targetWeight,
              calorieGoal: calories_goal,
              caloriesConsumed: caloriesIn,
              caloriesBurned: calories_burned,
              waterConsumpution: water,
              BMR: BMR,
              totalHoursSlept: sleep,
              REM: rem_sleep,
              RHR: rhr,
              totalStepsYesterday: totalStepsYesterday,
              totalStepsSoFar: totalStepsSoFar
            };

            return Profile.replaceOne({ _id: profile._id }, new_profile)
              .then(result => {
                console.log("got it done");
                res.redirect("/success");
              })
              .catch(err => {
                const error = new Error(err);
                error.httpStatusCode = 500;
                return next(error);
              });
          } else {
            const profile = new Profile({
              empID: empID,
              todaysDate: today,
              firstName: firstName,
              lastName: lastName,
              dateOfBirth: dateOfBirth,
              gender: gender,
              bodyStartWeight: startWeight,
              bodyTargetWeight: targetWeight,
              calorieGoal: calories_goal,
              caloriesConsumed: caloriesIn,
              caloriesBurned: calories_burned,
              waterConsumpution: water,
              BMR: BMR,
              totalHoursSlept: sleep,
              REM: rem_sleep,
              RHR: rhr,
              totalStepsYesterday: totalStepsYesterday,
              totalStepsSoFar: totalStepsSoFar
            });
            profile
              .save()
              .then(result => {
                console.log("got it done");
                res.redirect("/success");
              })
              .catch(err => {
                const error = new Error(err);
                error.httpStatusCode = 500;
                return next(error);
              });
          }
        });
      }) // end of update or insert
      .catch(err => {
        const error = new Error(err);
        error.httpStatusCode = 500;
        return next(error);
      });
  });
};

exports.getSuccess = (req, res, next) => {
  console.log("hello");
  res.status(200).render("authorize/success", {
    pageTitle: "Success",
    path: "/success"
  });
};

Open in new window

Bruce Gust

ASKER
OK!

I've made some progress, but I'm still not there...

This works, as far as entering a new row. Where it fails is in the context of updating that same row. No errors. I get redirected and I get my console message. But you'll see how I've hardcoded "8000" for the caloriesBurned value and that never gets changed.

Leak, I tried your approach and it wiped out everything save the id. Wanted to make sure you knew I was trying your suggestions...!

Here's what I've got. Why doesn't this script update what's in the database?

 Profile.findOne({ empID: empID, todaysDate: today })
          .then(person => {
            if (person) {
              // console.log(person[0][0].empID);
              console.log(calories_burned);
              _id: person._id;
              empID: empID;
              firstName: firstName;
              lastName: lastName;
              dateOfBirth: dateOfBirth;
              gender: gender;
              bodyStartWeight: startWeight;
              bodyTargetWeight: targetWeight;
              calorieGoal: calories_goal;
              caloriesConsumed: caloriesIn;
              caloriesBurned: 8000;
              waterConsumpution: water;
              BMR: BMR;
              totalHoursSlept: sleep;
              REM: rem_sleep;
              RHR: rhr;
              totalStepsYesterday: totalStepsYesterday;
              totalStepsSoFar: totalStepsSoFar;
              person
                .save()
                .then(result => {
                  console.log("updated");
                  res.redirect("/update");
                })
                .catch(err => {
                  const error = new Error(err);
                  return next(error);
                });
            } else {
              const profile = new Profile({
                empID: empID,
                todaysDate: today,
                firstName: firstName,
                lastName: lastName,
                dateOfBirth: dateOfBirth,
                gender: gender,
                bodyStartWeight: startWeight,
                bodyTargetWeight: targetWeight,
                calorieGoal: calories_goal,
                caloriesConsumed: caloriesIn,
                caloriesBurned: calories_burned,
                waterConsumpution: water,
                BMR: BMR,
                totalHoursSlept: sleep,
                REM: rem_sleep,
                RHR: rhr,
                totalStepsYesterday: totalStepsYesterday,
                totalStepsSoFar: totalStepsSoFar
              });
              profile
                .save()
                .then(result => {
                  console.log("got it done");
                  res.redirect("/success");
                })
                .catch(err => {
                  const error = new Error(err);
                  error.httpStatusCode = 500;
                  return next(error);
                });
            }
          })
          .catch(err => {
            const error = new Error(err);
            return next(error);
          });

Open in new window

All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
ASKER CERTIFIED SOLUTION
leakim971

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Bruce Gust

ASKER
We got it figured out, Leak! Thanks!