Hello everybody! I’m trying to pass the final test on my last project for this certification.
I’m using only one schema and pure MongoDB without mongoose. I know
I could do it with 2 schemas and mongoose, but I really want to learn how to
make queries inside an array that’s inside a document.
But I just cannot make it on my own.
Your code so far
//Here I'm trying to get only the objects inside the array inside user by limiting the dates:
let user = await usernames
.find({ _id: objectID(userId) }, { log: { date: { $gte: from } } })
.toArray();
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36.
I’ve edited your post for readability. When you enter a code block into a post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.
You can also use the “preformatted text” tool in the editor ( </> ) to add backticks around text.
Yes, I did look up the operators and mongodb aggregation framework.
The thing is that I want to limit the objects inside an array inside the document I’m searching the user by id and then inside this user’s document there is an array of exercise logs that I want to limit by the date they have. I’m receiving the
user and all my problem is the limiting of the array inside of the document
Im getting a ‘‘date’’ string from the url which I use to create a date object
to compare it with the log’s date object by using mongodb $gte but it doesnt seem to work. Please help
I decided to opt for a traditional JavaScript approach for this:
If there is a ‘from’ or ‘to’ query, create some dates as the default from and to. I set the default from to be 0 (1st jan 1970) and to to be the current time. If either the from or to query exists, replace these dates with those. Then call the filter() method on the array returning only the values between these dates. We can call the getTime() method on the dates to convert these into a numerical timestamp to compare.
/*Date Filter */
if(request.query.from || request.query.to){
let fromDate = new Date(0)
let toDate = new Date()
if(request.query.from){
fromDate = new Date(request.query.from)
}
if(request.query.to){
toDate = new Date(request.query.to)
}
result.log = result.log.filter((exerciseItem) =>{
let exerciseItemDate = new Date(exerciseItem.date)
return exerciseItemDate.getTime() >= fromDate.getTime()
&& exerciseItemDate.getTime() <= toDate.getTime()
})
}
responseObject = responseObject.toJSON()
responseObject['count'] = result.log.length
response.json(result)
This may not necessarily be the best approach since we are fetching all the data from the database unnecessarily, and moves the computation from MongoDB to our express app.
Hey! thanks for answering!
Yeah the JS way is really straightforward, but I wanted to learn about mongoDB
and experiment with it as much as I could.
I ended up using aggregation framework like this:
let usernames = db.collection('usernames');
//Passing
return async function(req, res){
let { userId, from, to, limit } = req.query;
userId = objectID(userId)
try {
//If there is no from in req.query, return everything since 1970
if(from){
from = new Date(from);
}
else{
from = new Date(0);
}
//if there is no to, return everything until today
if(to){
to = new Date(to);
}else{
to = new Date();
}
//if there is no limit then return a whole page
if(!limit){
limit = 100;
}
//Query to getting the logs array
let user = await usernames.aggregate([
{
//getting the right user by Id
$match:{
_id:userId
}
},
//Filtering the log array inside the user's document
{ $project:{
log:{
$filter:{
//Selecting the the array inside the user's document
input:"$log",
//selecting a name for every object inside the log's array
as:"log",
cond:{
//Limiting the log by the date
$and:[{$gte: ["$$log.date",from]},{$lte:["$$log.date",to]}]
}
}
},
//selecting which parameters to return with the user
username:1
},
},
{
//Limiting results
$limit:limit
}
]).toArray();
if (!user[0]) {
return res.status(404).send();
}
//Counting documents
user[0].count = user[0].log.length;
res.send(user[0]);
If you could check out my code and let me know what you think I would appreciate it!