DEV Community

loading...

Discussion on: How to build dynamic mongoose queries

Collapse
evanjameson profile image
Evan Jameson • Edited

Hi again! I followed your guide here and had a question:

When it comes to "${API}/search" where is API defined? Is the specified API path based on the request? Learning a lot from scratch here so this may be a rather rudimentary question.

Prior to following your guide I was getting the user specified value via req.query.params and using the path format "/:athleteName" where the request path would look like

-url here-/athletes/-name here-

What should the request look like when following your guide?

You can see my route here:

gist.github.com/EvanJameson/aebe11...

You can see my controller here:

gist.github.com/EvanJameson/2592d1...

Thread Thread
itz_giddy profile image
Audiophile Author

Hi Evan! I apologize for not being clear on the API path. In JavaScript it is advisable to always store values that are least likely to change in variables for two reasons: 1.) ease of use in multiple places 2.) It reduces typos. So usually if I have an endpoint like:

 'http://localhost:5000/api/students/search'
Enter fullscreen mode Exit fullscreen mode

My base url will be: localhost:5000/api/students while my search endpoint would be: /search. Now if I have 10 different endpoints doing different things, having to type my base url multiple times would slow me down. So instead I do something like:

 const API = 'http://localhost:5000/api/students'
Enter fullscreen mode Exit fullscreen mode

And then for each route path, I use es6 string literals to concatenate the base url and the search endpoint like so:

 router.get(`${API}/search`)
Enter fullscreen mode Exit fullscreen mode

So even if I have 20 routes to build, all I have to do is use string literals to concatenate the base url and route path:

 router.get(`${API}/route1`)

 router.get(`${API}/route2`)
 .
 .
 .
router.get(`${API}/route20`
Enter fullscreen mode Exit fullscreen mode

Now for the '/:athleteName' convention, there's nothing wrong in doing it that way, it's part of RESTful convention to show other developers that it is a query parameter. Although when testing the endpoint with Postman there is a slight difference in the way you would do it.

You see adding '/:athleteName' means that when sending your request(in Postman) you would have to type something like:

 'http://localhost:5000/api/athletes/Evan'
Enter fullscreen mode Exit fullscreen mode

in your get request. You may not be able to add it to the query params field in Postman to get something that looks more like:

 'http://localhost:5000/api/athletes?athleteName=Evan'
Enter fullscreen mode Exit fullscreen mode

You can see that the two requests are different even though you would eventually get the same result either way.

Here's the thing, your 'req' and 'res' are objects that have properties attached to each of them. The request object(req) has a 'query' property that is also an object. For example:

 const req = {
            query:{ athleteName }
             }
Enter fullscreen mode Exit fullscreen mode

So if I wanted to get the athleteName(in my controller function) from a get request without having to use the '/:athleteName' convention, I would just get it this way:

  const athleteName = req.query.athleteName;

   or with destructuring

const { athleteName } = req.query;
Enter fullscreen mode Exit fullscreen mode

Doing it this way means I can write routes like 'localhost:5000/api/athlete/athlete...' without having to use the colons. Subtle difference but doesn't stop your code from working, only changes how you would test with Postman(at least in my case it did). I hope this helps.

Thread Thread
awkwardblkcoder profile image
Phoebe M

I love how this reply was its own mini tutorial! lol so thorough

Thread Thread
itz_giddy profile image
Audiophile Author

Thanks Phoebe!