如何在Node.js中与Mongoose分页?

我正在写一个Node.js和mongoose的Web应用程序。 我如何分页从.find()调用得到的结果? 我想在SQL中可以使用与"LIMIT 50,100"相媲美的function。

我对这个问题的答案感到非常失望。 这不会缩放。 如果您阅读cursor.skip()上的精细打印:

cursor.skip()方法通常很昂贵,因为它要求服务器从集合或索引的开始处走开,以在开始返回结果之前获取偏移或跳过位置。 随着偏移量(例如上面的pageNumber)的增加,cursor.skip()将变得更慢并且CPU密集度更高。 对于较大的集合,cursor.skip()可能会成为IO绑定。

为了以可扩展的方式实现分页,将限制()和至less一个过滤标准结合起来,createdOndate适合多种用途。

 MyModel.find( { createdOn: { $lte: request.createdOnBefore } } ) .limit( 10 ) .sort( '-createdOn' ) 

在仔细研究了由Rodolphe提供的信息的Mongoose API之后,我想出了这个解决scheme:

 MyModel.find(query, fields, { skip: 10, limit: 5 }, function(err, results) { ... }); 

使用mongoose,快递和玉分页 – http://madhums.me/2012/08/20/pagination-using-mongoose-express-and-jade/

 var perPage = 10 , page = Math.max(0, req.param('page')) Event.find() .select('name') .limit(perPage) .skip(perPage * page) .sort({ name: 'asc' }) .exec(function(err, events) { Event.count().exec(function(err, count) { res.render('events', { events: events, page: page, pages: count / perPage }) }) }) 

你可以像这样连锁:

 var query = Model.find().sort('mykey', 1).skip(2).limit(5) 

使用exec执行查询

 query.exec(callback); 

你可以使用一个名为Mongoose Paginate的小包来简化它。

 $ npm install mongoose-paginate 

在您的路线或控制器后,只需添加:

 /** * querying for `all` {} items in `MyModel` * paginating by second page, 10 items per page (10 results, page 2) **/ MyModel.paginate({}, 2, 10, function(error, pageCount, paginatedResults) { if (error) { console.error(error); } else { console.log('Pages:', pageCount); console.log(paginatedResults); } } 

迟到总比不到好。

 var pageOptions = { page: req.query.page || 0, limit: req.query.limit || 10 } sexyModel.find() .skip(pageOptions.page*pageOptions.limit) .limit(pageOptions.limit) .exec(function (err, doc) { if(err) { res.status(500).json(err); return; }; res.status(200).json(doc); }) 

在这种情况下,您可以将查询page和/或limit到您的http url。 示例?page=0&limit=25

BTW分页以0开头

这是一个示例,你可以试试这个,

 var _pageNumber = 2, _pageSize = 50; Student.count({},function(err,count){ Student.find({}, null, { sort: { Name: 1 } }).skip(_pageNumber > 0 ? ((_pageNumber - 1) * _pageSize) : 0).limit(_pageSize).exec(function(err, docs) { if (err) res.json(err); else res.json({ "TotalCount": count, "_Array": docs }); }); }); 

这是我在代码上完成的

 var paginate = 20; var page = pageNumber; MySchema.find({}).sort('mykey', 1).skip((pageNumber-1)*paginate).limit(paginate) .exec(function(err, result) { // Write some stuff here }); 

我就是这么做的。

这是我附加到我的所有模型的版本。 这取决于下划线的方便性和asynchronous的性能。 select允许使用mongoose语法进行字段select和sorting。

 var _ = require('underscore'); var async = require('async'); function findPaginated(filter, opts, cb) { var defaults = {skip : 0, limit : 10}; opts = _.extend({}, defaults, opts); filter = _.extend({}, filter); var cntQry = this.find(filter); var qry = this.find(filter); if (opts.sort) { qry = qry.sort(opts.sort); } if (opts.fields) { qry = qry.select(opts.fields); } qry = qry.limit(opts.limit).skip(opts.skip); async.parallel( [ function (cb) { cntQry.count(cb); }, function (cb) { qry.exec(cb); } ], function (err, results) { if (err) return cb(err); var count = 0, ret = []; _.each(results, function (r) { if (typeof(r) == 'number') { count = r; } else if (typeof(r) != 'number') { ret = r; } }); cb(null, {totalCount : count, results : ret}); } ); return qry; } 

将其附加到您的模型模式。

 MySchema.statics.findPaginated = findPaginated; 

尝试使用mongoosefunction的分页。 限制是每个页面的logging数量和页面的数量。

 var limit = parseInt(body.limit); var skip = (parseInt(body.page)-1) * parseInt(limit); db.Rankings.find({}) .sort('-id') .limit(limit) .skip(skip) .exec(function(err,wins){ }); 

最简单和更快捷的方式是,与objectId示例分页;

初始负载条件

 condition = {limit:12, type:""}; 

从响应数据中获取第一个和最后一个ObjectId

下一页的条件

 condition = {limit:12, type:"next", firstId:"57762a4c875adce3c38c662d", lastId:"57762a4c875adce3c38c6615"}; 

下一页的条件

 condition = {limit:12, type:"next", firstId:"57762a4c875adce3c38c6645", lastId:"57762a4c875adce3c38c6675"}; 

在mongoose

 var condition = {}; var sort = { _id: 1 }; if (req.body.type == "next") { condition._id = { $gt: req.body.lastId }; } else if (req.body.type == "prev") { sort = { _id: -1 }; condition._id = { $lt: req.body.firstId }; } var query = Model.find(condition, {}, { sort: sort }).limit(req.body.limit); query.exec(function(err, properties) { return res.json({ "result": result); }); 

你可以写这样的查询。

 mySchema.find().skip((page-1)*per_page).limit(per_page).exec(function(err, articles) { if (err) { return res.status(400).send({ message: err }); } else { res.json(articles); } }); 

页面:来自客户端的页码作为请求参数。
per_page:每页显示的结果数量

如果您正在使用MEAN堆栈,则博客文章提供了许多信息,使用angular-UI bootstrap在前端创build分页,并在后端使用mongoose跳过和限制方法。

请参阅: https : //techpituwa.wordpress.com/2015/06/06/mean-js-pagination-with-angular-ui-bootstrap/

你可以使用skip()和limit(),但效率很低。 一个更好的解决scheme将是一个索引字段加limit()。 我们在Wunderflats已经发布了一个小的lib: https : //github.com/wunderflats/goosepage它使用第一种方法。

如果您使用mongoose作为restful api的源代码,请查看“ restify-mongoose ”及其查询。 它正是内置了这个function。

对集合的任何查询都提供了有用的标题

 test-01:~$ curl -s -D - localhost:3330/data?sort=-created -o /dev/null HTTP/1.1 200 OK link: </data?sort=-created&p=0>; rel="first", </data?sort=-created&p=1>; rel="next", </data?sort=-created&p=134715>; rel="last" ..... Response-Time: 37 

所以基本上你会得到一个通用的服务器,具有相对线性的加载时间来查询集合。 如果你想进入一个自己的实现,那真是太棒了。

 app.get("/:page",(req,res)=>{ post.find({}).then((data)=>{ let per_page = 5; let num_page = Number(req.params.page); let max_pages = Math.ceil(data.length/per_page); if(num_page == 0 || num_page > max_pages){ res.render('404'); }else{ let starting = per_page*(num_page-1) let ending = per_page+starting res.render('posts', {posts:data.slice(starting,ending), pages: max_pages, current_page: num_page}); } }); }); 

最好的方法(IMO)是在有限的集合或文档中使用跳过和限制BUT。

要在有限的文档中进行查询,我们可以在DATEtypes字段中使用特定索引(如索引)。 看到下面

 let page = ctx.request.body.page || 1 let size = ctx.request.body.size || 10 let DATE_FROM = ctx.request.body.date_from let DATE_TO = ctx.request.body.date_to var start = (parseInt(page) - 1) * parseInt(size) let result = await Model.find({ created_at: { $lte: DATE_FROM, $gte: DATE_TO } }) .sort({ _id: -1 }) .select('<fields>') .skip( start ) .limit( size ) .exec(callback)