feyen01
feyen01

Reputation: 417

How to filter data for API in Node/MongoDB?

I'm trying to write a simple API to get products from database. I want to filter this data by given specific params, which are optional:

router.get('/articles/:type?/:year?/:model?', api_controller.articles);

My controller looks like this:

exports.articles = async (req, res, next) => {
const articles = await Article.find({
    'models': {
        $elemMatch: {
            'year': req.params.year,
            'category': req.params.type,
            'name': req.params.model,
        }
    }
});
res.send(articles);

}

However this works only for URL with 3 params. How to flexible get data from database by querying API with no params, single param and multiple params?

Upvotes: 1

Views: 4014

Answers (1)

Paul
Paul

Reputation: 36339

So, you can't really do routing exactly like that. The concept of 'optional' route parameters doesn't work well with path params. For example, you're not able to search on just model the way you have it, if you want to specify model you need to put in type and year for sure.

If you must do it with the path, then you'll need to define three routes in reverse order of granularity:

router.get('/articles/:type/:year/:model', api_controller.articles);
router.get('/articles/:type/:year', api_controller.articles);
router.get('/articles/:type', api_controller.articles);

Not sure if your query is right since you didn't share your data structure, but in general if you try and match on null, mongodb will ignore the param, so you're set there I think.

Now, if it were me, I wouldn't match on path at all. Instead I'd just use a querystring for the search parameters, like so:

router.get('/articles', api_controller.articles);

Then in the controller:

// now someone calls /articles?year=2017&type=whatever or could call /articles?model=some-name
exports.articles = async (req, res, next) => {
  const articles = await Article.find({
    'models': {
        $elemMatch: {
            'year': req.query.year,
            'category': req.query.type,
            'name': req.query.model,
        }
    }
  });
  res.send(articles);
}

Upvotes: 2

Related Questions