在MongoDB中限制结果,但仍然获得全数?

问题描述:

对于速度,我想查询限制为10个结果在MongoDB中限制结果,但仍然获得全数?

db.collection.find(...).limit(10) 

不过,我也想知道总的算的,所以说“有124,但我只有10”。有没有一种高效的方法来做到这一点?

默认情况下,count()忽略limit()并计算整个查询的结果。 因此,当你举例这样做,var a = db.collection.find(...).limit(10); 运行a.count()会给你你的查询的总数。

cursor.count()应该忽略cursor.skip()cursor.limit()默认。

来源:http://docs.mongodb.org/manual/reference/method/cursor.count/#cursor.count

做数(1)包括限制和跳过。

+0

由于mongoengine的, '类型错误:with_limit_and_skip必须是True或False, count(True)会做这项工作 – kkzxak47 2017-09-14 05:57:34

@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 

    }); 

}); 

有使用推和切片的解决方案:https://stackoverflow.com/a/39784851/4752635

我prefe

  1. 首先进行筛选,然后按ID进行分组以获得过滤元素的数量。不要在这里过滤,这是没有必要的。
  2. 第二个查询过滤,排序和分页。

推送$$ 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 
      }); 
      } 
     }); 
    } 
    }); 
}); 
+1

请不要在多个问题中添加[相同的答案](http://stackoverflow.com/a/42143423/4687348)。回答最好的一个,并将其余标记为重复。请参阅[是否可以为几个问题添加重复答案?](http://meta.stackexchange.com/q/104227/347985) – FelixSFD 2017-02-09 17:47:39