Tho*_*mas 206 pagination mongoose mongodb node.js
我正在用Node.js和mongoose编写一个webapp.如何对.find()通话中的结果进行分页?我想要一个与"LIMIT 50,100"SQL 相媲美的功能.
Chr*_*kle 264
我对这个问题中接受的答案感到非常失望.这不会扩展.如果您在cursor.skip()上阅读了精细打印:
cursor.skip()方法通常很昂贵,因为它要求服务器从集合或索引的开头走,以在开始返回结果之前获取偏移或跳过位置.随着偏移量(例如上面的pageNumber)的增加,cursor.skip()将变得更慢并且CPU密集度更高.对于较大的集合,cursor.skip()可能会成为IO绑定.
为了以可扩展的方式实现分页,将limit()与至少一个过滤标准结合起来,createdOn日期适合于许多目的.
MyModel.find( { createdOn: { $lte: request.createdOnBefore } } )
.limit( 10 )
.sort( '-createdOn' )
Run Code Online (Sandbox Code Playgroud)
Tho*_*mas 209
在仔细查看了使用Rodolphe提供的信息的Mongoose API之后,我找到了这个解决方案:
MyModel.find(query, fields, { skip: 10, limit: 5 }, function(err, results) { ... });
Run Code Online (Sandbox Code Playgroud)
Mad*_*han 94
使用猫鼬,快递和玉的分页 - 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
})
})
})
Run Code Online (Sandbox Code Playgroud)
Rod*_*phe 55
你可以这样链:
var query = Model.find().sort('mykey', 1).skip(2).limit(5)
Run Code Online (Sandbox Code Playgroud)
使用执行查询 exec
query.exec(callback);
Run Code Online (Sandbox Code Playgroud)
CEN*_*EDE 33
迟到总比不到好.
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);
})
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您可以将查询page和/或添加limit到您的http网址.样品?page=0&limit=25
BTW
分页开始于0
Clé*_*aud 32
你可以使用一个名为Mongoose Paginate的小包装,这样可以更容易.
$ npm install mongoose-paginate
Run Code Online (Sandbox Code Playgroud)
在您的路线或控制器之后,只需添加:
/**
* 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);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 22
询问:
search = productName
Run Code Online (Sandbox Code Playgroud)
参数:
page = 1
Run Code Online (Sandbox Code Playgroud)
// Pagination
router.get("/search/:page", (req, res, next) => {
const resultsPerPage = 5;
let page = req.params.page >= 1 ? req.params.page : 1;
const query = req.query.search;
page = page - 1
Product.find({ name: query })
.select("name")
.sort({ name: "asc" })
.limit(resultsPerPage)
.skip(resultsPerPage * page)
.then((results) => {
return res.status(200).send(results);
})
.catch((err) => {
return res.status(500).send(err);
});
});
Run Code Online (Sandbox Code Playgroud)
Lib*_*hew 15
这是一个示例您可以试试这个,
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
});
});
});
Run Code Online (Sandbox Code Playgroud)
小智 11
尝试使用mongoose功能进行分页.限制是每页的记录数和页数.
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){
});
Run Code Online (Sandbox Code Playgroud)
小智 9
这就是我在代码上所做的
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
});
Run Code Online (Sandbox Code Playgroud)
这就是我做的方式.
简单而强大的分页解决方案
async getNextDocs(no_of_docs_required: number, last_doc_id?: string) {
let docs
if (!last_doc_id) {
// get first 5 docs
docs = await MySchema.find().sort({ _id: -1 }).limit(no_of_docs_required)
}
else {
// get next 5 docs according to that last document id
docs = await MySchema.find({_id: {$lt: last_doc_id}})
.sort({ _id: -1 }).limit(no_of_docs_required)
}
return docs
}
Run Code Online (Sandbox Code Playgroud)
last_doc_id:您获得的最后一个文档 ID
no_of_docs_required:您要获取的文档数量,即 5、10、50 等。
last_doc_id方法,您将获得 ie 5 个最新文档last_doc_id那么您将获得接下来的 5 个文件。这是我附加到所有模型的版本.它取决于下划线以方便和异步性能.opts允许使用mongoose语法进行字段选择和排序.
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;
}
Run Code Online (Sandbox Code Playgroud)
将其附加到您的模型架构.
MySchema.statics.findPaginated = findPaginated;
Run Code Online (Sandbox Code Playgroud)
上面的答案很好。
对于任何喜欢 async-await 而不是 promise 的人来说,这只是一个附加组件!!
const findAllFoo = async (req, resp, next) => {
const pageSize = 10;
const currentPage = 1;
try {
const foos = await FooModel.find() // find all documents
.skip(pageSize * (currentPage - 1)) // we will not retrieve all records, but will skip first 'n' records
.limit(pageSize); // will limit/restrict the number of records to display
const numberOfFoos = await FooModel.countDocuments(); // count the number of records for that model
resp.setHeader('max-records', numberOfFoos);
resp.status(200).json(foos);
} catch (err) {
resp.status(500).json({
message: err
});
}
};
Run Code Online (Sandbox Code Playgroud)
有一些很好的答案给出了使用 skip() 和 limit() 的解决方案,但是,在某些情况下,我们还需要文档计数来生成分页。以下是我们在项目中所做的:
const PaginatePlugin = (schema, options) => {
options = options || {}
schema.query.paginate = async function(params) {
const pagination = {
limit: options.limit || 10,
page: 1,
count: 0
}
pagination.limit = parseInt(params.limit) || pagination.limit
const page = parseInt(params.page)
pagination.page = page > 0 ? page : pagination.page
const offset = (pagination.page - 1) * pagination.limit
const [data, count] = await Promise.all([
this.limit(pagination.limit).skip(offset),
this.model.countDocuments(this.getQuery())
]);
pagination.count = count;
return { data, pagination }
}
}
mySchema.plugin(PaginatePlugin, { limit: DEFAULT_LIMIT })
// using async/await
const { data, pagination } = await MyModel.find(...)
.populate(...)
.sort(...)
.paginate({ page: 1, limit: 10 })
// or using Promise
MyModel.find(...).paginate(req.query)
.then(({ data, pagination }) => {
})
.catch(err => {
})
Run Code Online (Sandbox Code Playgroud)
您也可以使用以下代码行
per_page = parseInt(req.query.per_page) || 10
page_no = parseInt(req.query.page_no) || 1
var pagination = {
limit: per_page ,
skip:per_page * (page_no - 1)
}
users = await User.find({<CONDITION>}).limit(pagination.limit).skip(pagination.skip).exec()
Run Code Online (Sandbox Code Playgroud)
该代码将在最新版本的 mongo 中运行
实现此目的的可靠方法是使用查询字符串从前端传递值。假设我们想要获取第 2页 ,并将输出限制为25个结果。
查询字符串将如下所示:?page=2&limit=25 // this would be added onto your URL: http:localhost:5000?page=2&limit=25
我们看一下代码:
// We would receive the values with req.query.<<valueName>> => e.g. req.query.page
// Since it would be a String we need to convert it to a Number in order to do our
// necessary calculations. Let's do it using the parseInt() method and let's also provide some default values:
const page = parseInt(req.query.page, 10) || 1; // getting the 'page' value
const limit = parseInt(req.query.limit, 10) || 25; // getting the 'limit' value
const startIndex = (page - 1) * limit; // this is how we would calculate the start index aka the SKIP value
const endIndex = page * limit; // this is how we would calculate the end index
// We also need the 'total' and we can get it easily using the Mongoose built-in **countDocuments** method
const total = await <<modelName>>.countDocuments();
// skip() will return a certain number of results after a certain number of documents.
// limit() is used to specify the maximum number of results to be returned.
// Let's assume that both are set (if that's not the case, the default value will be used for)
query = query.skip(startIndex).limit(limit);
// Executing the query
const results = await query;
// Pagination result
// Let's now prepare an object for the frontend
const pagination = {};
// If the endIndex is smaller than the total number of documents, we have a next page
if (endIndex < total) {
pagination.next = {
page: page + 1,
limit
};
}
// If the startIndex is greater than 0, we have a previous page
if (startIndex > 0) {
pagination.prev = {
page: page - 1,
limit
};
}
// Implementing some final touches and making a successful response (Express.js)
const advancedResults = {
success: true,
count: results.length,
pagination,
data: results
}
// That's it. All we have to do now is send the `results` to the frontend.
res.status(200).json(advancedResults);
Run Code Online (Sandbox Code Playgroud)
我建议将此逻辑实现到中间件中,以便您可以将其用于各种路由/控制器。
| 归档时间: |
|
| 查看次数: |
169342 次 |
| 最近记录: |