As the title says, I am trying to get specific data from the user when they are logged in and aggregate all the data and then return the aggregated data. I tried using the $match
function but no luck. What's frustrating is that I'm able to successfully return all the data in the object array. More specifically, the following code runs successfully and returns an array of objects:
const runs = await Run.find({ user: req.user.id })
But this code doesn't, it returns an empty array:
const cumulativeTotals = await Run.aggregate([ { $match: { user: req.user.id } }, { $group: { _id: null, totalRunTime: { $sum: '$runTime' }, avgRunTime: { $avg: '$runTime' }, totalRunDistance: { $sum: '$runDistance' }, avgRunDistance: { $avg: '$runDistance' }, avgPace: { $avg: '$avgPace' }, totalHeartRate: { $avg: '$avgHeartRate' }, totalActiveCalories: { $sum: '$activeCalories' }, averageActiveCalories: { $avg: '$activeCalories' }, absoluteTotalCalories: { $sum: '$totalCalories' }, avgTotalCalories: { $avg: '$totalCalories' }, } } ])
I'm not sure why this is happening. What it should return is an array with an object populated with all the aggregated data in it.
I also know that if I remove $match
it will successfully aggregate all the data in the running collection, so I think that has something to do with that.
Here are all the relevant codes:
const getRuns = asyncHandler(async (req, res) => { const runs = await Run.find({ user: req.user.id }) const cumulativeTotals = await Run.aggregate([ { $match: { user: req.user.id } }, { $group: { _id: null, totalRunTime: { $sum: '$runTime' }, avgRunTime: { $avg: '$runTime' }, totalRunDistance: { $sum: '$runDistance' }, avgRunDistance: { $avg: '$runDistance' }, avgPace: { $avg: '$avgPace' }, totalHeartRate: { $avg: '$avgHeartRate' }, totalActiveCalories: { $sum: '$activeCalories' }, averageActiveCalories: { $avg: '$activeCalories' }, absoluteTotalCalories: { $sum: '$totalCalories' }, avgTotalCalories: { $avg: '$totalCalories' }, } } ]) if (!runs) { res.status(400).json({ message: 'No Runs Found for This User' }) return } const response = { runs, cumulativeTotals } res.status(200).json(response) })
So with the help of rickhg12hs we were able to determine that
{match: { user : req.user.id } }
is me trying to compare a string to an ObjectId, this will not work. This is because the API I set up returns the user ID as a string, not as an ObjectID. To make sure you're comparing the correct value type (ObjectID in this case), you can do this:It takes the returned string and converts it to a new ObjectID, and since it's now comparing ObjectIDs, it works.
Apparently it was in the documentation all along, I just didn't look carefully enough