How to separate the logic of the interface in queries with mongodb and nodejs

Asked

Viewed 49 times

-2

I’m studying Mongodb and Nodejs, I’m starting . I downloaded an example code from git and started to customize. The original query code was like this:

router.get('/products/:page', (req, res, next) => {
                 
   let perPage = 9;
   let page = req.params.page || 1;

   Product
     .find({}) // finding all documents
     .skip((perPage * page) - perPage) // in the first page the value of the skip is 0
     .limit(perPage) // output just 9 items
     .exec((err, products) => {
       Product.count((err, count) => { // count to calculate the number of pages
         if (err) return next(err);
         res.render('products/products', {
           products,
           current: page,
           pages: Math.ceil(count / perPage)
         });
       });
     });
});

However I need to separate the logic of the query from the router, so I created this source:

const Product = require('../produto/product');


exports.ListaProdutos = async (req, res, next) => {
        let perPage = 9;
        let page = req.params.page || 1;
      
        await Product
          .find({}) // finding all documents
          .skip((perPage * page) - perPage) // in the first page the value of the skip is 0
          .limit(perPage) // output just 9 items
          .exec((err, products) => {
            Product.count((err, count) => { // count to calculate the number of pages
              if (err) {
                  return next(err)}
              else {
                 res.render('products/products', {
                 products,
                 current: page,
                 pages: Math.ceil(count / perPage)
               })
            };
            });
          });
};

And my router changed this code:

router.get('/products/:page', (req, res, next) => { Listproducts(req, res, next);

});

It continues to work perfectly. However, if you notice inside the List Products method, I still answer the query with a res.render('products/products'. I wouldn’t want it to be like this. I would like the List Products method to return only the data and the router only tested if the return has data and ran the res.render.

How do I do this? I tried to :

if (err) {
   return next(err)}
else {
   return products;
     };

But this way I do not know how to treat the function return on the router. And there is another aggravating factor that is the pagination that the original code implements. How will I pass to the router the variables: perpage and page?

Another question: It’s right what I’m trying to implement?

Anyway, I’m more lost than blind in a gunfight. I need to learn, but I want to learn the right way.

Thank you all.

1 answer

-1

Well, the sample code you took in Git was implemented in a didactic way, for easy understanding. So everything is done in the same file and in the same block of code. But in a production application things are not done like that. In web development for example, usually follows some development pattern, such as the MVC (Model, View, Controller). The Model contains the class scope of the objects your application handles, the controller encompasses all methods that manipulate these model objects and the view is what is returned to the user.

You said you wanted the router to be separate from the query. This query is nothing more than the controller of this Products model you created. The router is a routing only, it should not perform any task other than just referencing the controller according to the accessed url. Therefore, it is the responsibility of the controller to query and return the data, in the case with a res.render. Still under development pattern the routes may also have a pattern as for example the REST.

Finally, I recommend studying a bit about web software architecture. This will show you a little bit about the MVC standard and the division of code in the application for easy understanding of any developer who enters the project.

  • This part I understood, but what I need to know is: If where I declare the exports.List products I can use res.render or this should stay on the router?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.