Exercise tracker. problem while collecting data from DB

I have added a path for collecting user exercise logs. I can get data from a particular date range but if there is no exercise log I am getting my custom error.

How can I get a user with an empty log?

This is the route where I am having a problem

//GET full exercise log of user 
app.get("/api/exercise/log",async(req,res)=>{   // from to date in yyyy-mm-dd format and limit
	try{
		let from = moment(req.query.from).toDate();
    let to = moment(req.query.to ).toDate();
		let foundUser = await User.aggregate( [{$match: { _id: mongoose.Types.ObjectId(req.query.userId)}},
																					 {$unwind: "$log"},
																					 {$match: {"log.date":{$gte:from,$lte:to}}},
																					 {$group:{'_id':'$_id','username':{"$first":'$username'},'from':{"$first":from},'to':{"$first":to},'log':{$push:'$log'}}}]) //

		if(foundUser.length > 0){
			console.log("found user", foundUser)
			res.json(foundUser[0])
		} else{
			throw new Error("User not found")
		}
	}catch(error){
		res.json({error: error.message})
	}
})

Github Repo

This depends on how detailed you want your error message to be. Right now, User not found isn’t correct, it could be that either there’s no user with that ID in the database, or that their exercises array is empty.

I wouldn’t make it too complicated. You can just fetch the user and filter/limit the array in your route code on the server. But if you want to make it work with aggregation (I can relate, I tried the same but in the end couldn’t be bothered), I think you’d need to modify your stages so that you either

  • get a result if the user is found
  • get no result if no user is found

The problem is, whenever you $unwind with an empty array, obviously you’d get no result, and you’d have no way of telling what’s the reason. You can however add a configuration object to $unwind:

{$unwind: {
    path: "$log",
    preserveNullAndEmptyArrays: true
    }
}

This way, you’ll still have a result document after $unwind, with all fields except a log field. I’m not sure though what’s going to happen if you add a $match and $group stage, where you perform queries on a non-existent field.

Figuring this out could be interesting, but you’ll have to decide if you want to make the effort.

Thank you for the suggestion!

Now I am using $addfield to include the ‘log’ field. and with conditions applied I can get desired exercise log. let me know if I can improve this approach as well…

I wouldn’t know, I’ve started learning about aggregation only a short while ago. If it’s working now (also for cases where there are no dates from/to or a limit in req.query), I’d leave it like it is. This goes far beyond what the challenge expects you to do anyway, I think the “official” solution performs only a .findById and handles all the filtering of the exercises with JS array methods.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.