Trouble Understanding Express and Mongoose

Dear all,

I am currently trying to tackle the Exercise Tracker challenge from the APIs and Microservices unit and I really feel stuck.

I read through the hints and questions of others regardings this challenge in this forum and looked into the test suite, but I can’t seem to make it pass tests 4 to 7. If I test manually, however, it seems fine to me as the output and the data types should be correct. I currently don’t really see why it doesn’t work. :thinking:

This is my project so far:

Is there a way to see the errors the tests return using Replit? This would probably help me already.

I tried to change dates inside an object returned by a Schema.find() function into strings, but this was not possible. (Are objects returned by Mongoose immutable regarding the data types?) Hence, I re-built the object in order to make the date format consistent with the format the test seems to require. There is probably a way to achieve this in a less complicated way. In the end, this did not help to pass the test anyways.

I think that it would have been nice to have a few more hints in the description to make this challenge a bit less challenging. Actually, it seems to me that the whole unit does not really provide much information for people like me who are totally new to Node.js, Express and MongoDB. I really felt a bit lost when I went through this unit. So, any suggestions on how to optimize my code are highly appreciated!

Thanks a lot!

Didn’t run your code, but just by looking at it I think the problem is that in createExercise middleware you’re trying to access :_id which doesn’t exist.
Try to remove semicolon (i.e. _id).

1 Like

Thank you! Actually, this should be fine, because it refers to the name of the field for the user id when you enter a new exercise. Its name is :_id and if I access the value of this reference, it is correct. I just found that my middleware chaining was wrong, so the validations I set up would not be called at the right moment. I changed this, but the problem persists.


After a second thought, I realized that I am amazingly stupid! Of course this field’s name is :_id, since when the form is posted, this is the value that will be put inside the URL. I now changed req.body[':_id'] to req.params._id and, guess what, tests number 4 and 6 pass. Great! The other tests passed after I corrected the key for the log as was required by the challenge. Thank you again for pointing me in the right direction!


Ok, so this was indeed the culprit. But I am still curious: When I tried console.log(req.body[':_id']), this still returned the value of the field. For example, req.body would return:

  ':_id': '6095d304434bb0003955b0e7',
  description: 'sleeping',
  duration: '120',
  date: ''

And then, you would be able to access the first item with req.body[':_id']. So, where exactly is the difference then to accessing req.params._id form the URL? Or is it just the test that is a bit picky here?


Sorry for repeatedly answering my own questions. I looked into the test suite again, and it seems that it really does not submit the full form when testing the creation of exercises, but it only posts a description and duration (and date) to the URL where the id is served as parameter. Hence, my set-up would not work in this situation, because the field :_id would remain empty in this case.

Object.:_id is the same value as Object[':_id'].

There is a reson for different notation and it is explained here.

TLDR:
When you have a string as a property name, you can’t always access it with dot notation. Why? Because of some characters.

obj = {'property name long' : 'some value'}

This object is valid.

obj.property name long is not precise and there will be an error. JS have no way of knowing that after a space there is still something to check. It is looking for obj.property (ommiting name long).
obj['property name long'] is precise.

Hope that helps.

1 Like

Thank you for the explanation! Sometimes one really has to brush up on one’s knowledge!

As for the objects that are returned by Mongoose, I found (on StackOverflow) that they indeed seem to be some kind of special object (namely instances of the Mongoose Document class), and therefore data types of these objects cannot easily be changed. It seems to be possible, however, to use .lean() to return a regular Javascript object.

So, for instance in this code (where ExTrackerExercise is the schema where all the exercises are stored), .toDateString() would have no effect and the code would still return the dates as date objects:

app.get('/api/test', (req, res) => {
  ExTrackerExercise.find().exec(function (err, result) {
    if (err) return console.log(err); 
    result.forEach(entry => {entry.date = entry.date.toDateString() });
    res.json(result);
  });
});

But with .lean() added, the code would work as expected and all the dates would be converted to date strings:

app.get('/api/test', (req, res) => {
  ExTrackerExercise.find().lean().exec(function (err, result) {
    if (err) return console.log(err); 
    result.forEach(entry => {entry.date = entry.date.toDateString() });
    res.json(result);
  });
});

It should also be possible to use .toObject() to convert the Mongoose object into a plain Javascript object (but I have not try this myself).

1 Like

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