从多个Mongoose查询中收集数据并发送到路由

时间:2017-09-16 08:49:35

标签: javascript node.js mongodb express mongoose

刚开始学习Express,在线提供内容。页面取决于我能够管理的单个查询。但我坚持使用页面,我必须建立一个分页表。在这里,我必须首先调用2个查询以获得总计数,然后调用第二个数据集的第1页(限制20)。我正在使用Bootstrap表,它通过ajax调用在页面加载后呈现数据。响应应采用以下格式 -

{"total":100,"rows":[{"id":"59af010d93f3cc9ab0e09b3a","email":"test@test.com"},
{"id":"59af010d93f3cc9ab0e09b3a","email":"test2@test.com"}]}}

我有一个路由文件 - users.js,我在调用我的模型 - users.js

的路由/ users.js

const User = require('../models/user');

router.get('/userslist', (req, res) => {
  User.getUserList(req, (err, user,next) => {
    if(err) throw err;
    if(!user){
      return res.json({success: false, msg: 'User not found'});
    }
      res.json({"rows":user});
  });  
});
module.exports = router;

模型/ user.js的

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

module.exports.getUserList = function(req, callback){

    skip = parseInt(req.query.offset);
    nPerPage = parseInt(req.query.limit);
    sortby = req.query.sort;
    orderby = req.query.order;

    User.find().exec(function (err, count){
          User.find(callback).sort([[sortby, orderby]]).skip(skip > 0 ? (skip+1) : 0).limit(nPerPage).exec(function(err, data){
            res.json( {"total":count.length,"rows":data} );
          });
})

在这个模型文件中,我试图一起调用2个查询,这就是抛出错误。但是当我只调用没有res.json的第二个查询时,它就可以工作。

请告诉我调用多个查询的最佳做法是什么,以及如何提高我对回调的理解。我觉得那是我完全空白的地方。如果您可以通过简单的示例推荐任何在线内容,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

这不是发出回调的正确方法。而你的重大问题是res不在范围内。但是还有其他一些你应该注意的事情。

而是将结果(数据和/或错误)传递给调用函数并在那里解析:

的路由/ users.js

const User = require('../models/user');

router.get('/userslist', (req, res, next) => {
  User.getUserList(req, (err, data) => {
    if(err) next(err);
    if(!data){
      return res.json({success: false, msg: 'User not found'});
    }
    res.json(data);
  });  
});
module.exports = router;

模型/ user.js的

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

module.exports.getUserList = function(req, callback) {

    skip = parseInt(req.query.offset);
    nPerPage = parseInt(req.query.limit);
    sortby = req.query.sort;
    orderby = req.query.order;

    User.count().exec((err, count) => {
      User.find().sort([[sortby, orderby]])
        .skip(skip > 0 ? (skip+1) : 0).limit(nPerPage)
        .exec((err, data) => {
          callback(err,{"total":count,"rows":data});
        });
    })
}

或者更好的是,学会使用承诺:

的路由/ users.js

const User = require('../models/user');

router.get('/userslist', (req, res, next) => {
  User.getUserList(req).then(data => {
    if(!data) {
      return res.json({success: false, msg: 'User not found'});
    }
    res.json(data);
  }).catch(next);
});
module.exports = router;

模型/ user.js的

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

module.exports.getUserList = function(req) {

    skip = parseInt(req.query.offset);
    nPerPage = parseInt(req.query.limit);
    sortby = req.query.sort;
    orderby = req.query.order;

    return User.count().then(count =>
      User.find().sort([[sortby, orderby]])
        .skip(skip > 0 ? (skip+1) : 0)
        .limit(nPerPage).then(data => ({"total":count,"rows":data}))
    );

}

甚至使用async/await进行现代化,并使计数和数据请求与Promise.all()并行

的路由/ users.js

const User = require('../models/user');

router.get('/userslist', async (req, res, next) => {
  try {
    let data = await User.getUserList(req)
    if(!data) {
      return res.json({success: false, msg: 'User not found'});
    }
    res.json(data);
  } catch(e) {
    next(e);
  }
});
module.exports = router;

模型/ user.js的

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

module.exports.getUserList = (req) => {

    skip = parseInt(req.query.offset);
    nPerPage = parseInt(req.query.limit);
    sortby = req.query.sort;
    orderby = req.query.order;

    return Promise.all([
      User.count().then(count => ({ total: count })),
      User.find().sort([[sortby, orderby]])
        .skip(skip > 0 ? (skip+1) : 0)
        .limit(nPerPage)
        .then( data => ({ rows: data }))
    ]).then(result => result.reduce((acc,curr) =>
      Object.assign(acc,curr),{})
    );

}

在任何一种情况下,通过控制器返回数据都不是模型函数的任务。而是将数据传回,让控制器上的方法实际执行输出。

  

另请注意,使用.count()优先于.find(),然后获取结果数组的长度。前者效率更高,因为它从"光标"得到结果计数。而实际上并不需要迭代并返回光标中的所有文档,这就是后者正在做的事情。