对于速度,我想将查询限制为10个结果
db.collection.find( ... ).limit(10)
但是,我也想知道总数,所以说“有124只,但我只有10只”。有没有一种很有效的方法来做到这一点?
答案 0 :(得分:36)
默认情况下,count()
会忽略limit()
并计算整个查询中的结果。
所以当你这样做时,var a = db.collection.find(...).limit(10);
正在运行a.count()
将为您提供查询总数。
答案 1 :(得分:24)
执行count(1)包括限制和跳过。
答案 2 :(得分:5)
cursor.count()
默认会忽略cursor.skip()
和cursor.limit()
。
来源:http://docs.mongodb.org/manual/reference/method/cursor.count/#cursor.count
答案 3 :(得分:5)
@johnnycrab接受的答案是针对mongo CLI。
如果你必须在Node.js和Express.js中编写相同的代码,你必须像这样使用它才能使用" count"功能以及toArray"结果"。
var curFind = db.collection('tasks').find({query});
然后你可以像这样运行两个函数(一个嵌套在另一个函数中)
curFind.count(function (e, count) {
// Use count here
curFind.skip(0).limit(10).toArray(function(err, result) {
// Use result here and count here
});
});
答案 4 :(得分:0)
使用推送和切片有一个解决方案:https://stackoverflow.com/a/39784851/4752635
我优先
推送$$ ROOT并使用$ slice的解决方案运行到大型集合的16MB的文档内存限制。此外,对于大型集合,两个查询似乎比使用$$ ROOT推送的查询运行得更快。您也可以并行运行它们,因此您只受两个查询中较慢的查询(可能是排序的查询)的限制。
我已经使用2个查询和聚合框架解决了这个问题(注意 - 在这个例子中我使用了node.js,但想法是一样的):
var aggregation = [
{
// If you can match fields at the begining, match as many as early as possible.
$match: {...}
},
{
// Projection.
$project: {...}
},
{
// Some things you can match only after projection or grouping, so do it now.
$match: {...}
}
];
// Copy filtering elements from the pipeline - this is the same for both counting number of fileter elements and for pagination queries.
var aggregationPaginated = aggregation.slice(0);
// Count filtered elements.
aggregation.push(
{
$group: {
_id: null,
count: { $sum: 1 }
}
}
);
// Sort in pagination query.
aggregationPaginated.push(
{
$sort: sorting
}
);
// Paginate.
aggregationPaginated.push(
{
$limit: skip + length
},
{
$skip: skip
}
);
// I use mongoose.
// Get total count.
model.count(function(errCount, totalCount) {
// Count filtered.
model.aggregate(aggregation)
.allowDiskUse(true)
.exec(
function(errFind, documents) {
if (errFind) {
// Errors.
res.status(503);
return res.json({
'success': false,
'response': 'err_counting'
});
}
else {
// Number of filtered elements.
var numFiltered = documents[0].count;
// Filter, sort and pagiante.
model.request.aggregate(aggregationPaginated)
.allowDiskUse(true)
.exec(
function(errFindP, documentsP) {
if (errFindP) {
// Errors.
res.status(503);
return res.json({
'success': false,
'response': 'err_pagination'
});
}
else {
return res.json({
'success': true,
'recordsTotal': totalCount,
'recordsFiltered': numFiltered,
'response': documentsP
});
}
});
}
});
});