如何在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)