【发布时间】:2016-04-28 23:36:05
【问题描述】:
我有一个包含许多对象的 json 数据。我想限制分页数据,我需要总项目数。请帮忙。
Model.find().skip((pageNumber-1)*limit).limit(limit).exec()
我想要计数和跳过的数据作为响应。
【问题讨论】:
标签: node.js database mongodb mongoose aggregation-framework
我有一个包含许多对象的 json 数据。我想限制分页数据,我需要总项目数。请帮忙。
Model.find().skip((pageNumber-1)*limit).limit(limit).exec()
我想要计数和跳过的数据作为响应。
【问题讨论】:
标签: node.js database mongodb mongoose aggregation-framework
您需要执行 2 次查询才能实现这一目标。一个获取结果,另一个获取.count() 的总项目金额。
例如,您可以在“paginator”上观看 mongoose mongoose-paginate 的代码。
【讨论】:
您可以使用异步库一次运行 2 个查询。在您的情况下,您可以运行一个查询来获取文档的数量,另一个用于分页。
“用户”模型示例:
var async = require('async');
var User = require('./models/user');
var countQuery = function(callback){
User.count({}, function(err, count){
if(err){ callback(err, null) }
else{
callback(null, count);
}
}
};
var retrieveQuery = function(callback){
User.find({}).skip((page-1)*PAGE_LIMIT)
.limit(PAGE_LIMIT)
.exec(function(err, doc){
if(err){ callback(err, null) }
else{
callback(null, doc);
}
}
};
async.parallel([countQuery, retrieveQuery], function(err, results){
//err contains the array of error of all the functions
//results contains an array of all the results
//results[0] will contain value of doc.length from countQuery function
//results[1] will contain doc of retrieveQuery function
//You can send the results as
res.json({users: results[1], pageLimit: PAGE_LIMIT, page: page, totalCount: results[0]});
});
async 允许您根据所使用的硬件并行运行多个查询。这比使用 2 个独立查询来获取计数和获取所需文档要快。 希望这会有所帮助。
【讨论】:
这些解决方案的问题在于,对于每个请求,您都会执行两个查询。当您拥有复杂的数据结构和大型数据集时,这会成为问题,因为性能会成为问题。考虑创建一个特殊函数来侦听/resource?count=true 或/resource/count GET 方法并仅返回计数。
【讨论】:
要只执行一个查询,您可以使用与 Promise 和数组切片相关联的 find() 方法。一个小例子是:
getPaginated(query, skip, limit){
return this.model.find(query)
.lean()
.then((value)=>{
if (value.length === 0) return {userMessage: 'Document not found'};
const count = value.length;
//skip===0 must be handled
const start = parseInt(limit)*parseInt(skip - 1);
const end = start + parseInt(reqQuery.pagesize);
//slicing the array
value = value.slice(start,end);
//could return it another way...
value.push( { 'querySize': count });
return value;
})
.catch((reason)=>{
//...handling code
});
}
【讨论】:
我在 mongoose v3+ 中用$facet 和aggregate 解决了这个问题:
const [{ paginatedResult, [{ totalCount }] }] = await Model.aggregate([{
$facet: {
paginatedResult: [
{ $match: query },
{ $skip: skip },
{ $limit: limit }
],
totalCount: [
{ $match: query },
{ $count: 'totalCount' }
]
}
}])
其中totalCount 是指与搜索查询匹配的记录总数,而paginatedResult 只是它们的分页切片。
【讨论】: