使用 Mongoose 查找和计数集合元素

Posted

技术标签:

【中文标题】使用 Mongoose 查找和计数集合元素【英文标题】:Find and Count elements of collection with Mongoose 【发布时间】:2016-05-28 09:31:35 【问题描述】:

在 Mongoose 中,我需要在集合中查找元素并对其进行计数,并同时获取查找和计数的结果。我试过了

Model.find().count(function (err, count) 
    // Get count, but cannot get results of find
);

有没有办法在不调用两次的情况下同时获取 find() 和 count()?

【问题讨论】:

【参考方案1】:

可以使用返回数组的长度:

Model.find().exec(function (err, results) 
  var count = results.length

);

【讨论】:

这里.exec的目的是什么? 这只是一种编码风格,你可以这样写:Model.find(, function(err, results) ),检查这个:mongoosejs.com/docs/api.html#model_Model.find @MarcB 虽然这不是最好的解释,但这在技术上是正确的,并且比您目前接受的答案更有效。这是猫鼬通过“自动”将结果转换为“数组”来处理结果光标的方式的产物。因此,合乎逻辑的做法是将数组“长度”作为“计数”返回。这避免了做两次。只有当您想将“光标”直接用作“流”时,才需要运行单独的计数。但这可以说是在流处理中处理的。 @BlakesSeven 对不起,我实际上是在评论原始答案。我想这真的取决于您希望如何使用“计数”。我在这里做了几个假设。我考虑了 webapp 上下文中的实际实现以及为什么需要计数。这可能是您希望向用户展示的内容:“显示 32results.length 结果:”后跟结果列表。但是,如果数据集达到数千个条目怎么办。你需要这样的东西:'显示 4331 个结果中的 50 个结果 results.length === 50'。 @user1695032 没错,但关键是“大响应”对于会导致数组的调用语法来说是脱离上下文的。这不是给出的答案,但我确实在评论中为“大结果”添加了“流”上下文(以添加该值)。是的,您也可以“流式传输”JSON 编写器输出。因此,在不使用 .count() 作为附加调用的情况下,大结果中的计数是有效的。只有在“分页”时才需要它。当你当然应该总是使用两个查询时。一个用于完整计数,另一个用于当前页面。【参考方案2】:

很遗憾,您必须执行 2 个单独的查询。 Festo 的答案只有在数据库中的元素少于限制时才有效。

var countQuery = Model.count();
var findQuery = Model.find().limit(2);

countQuery.exec(function (e, count) 
  console.log('count', count); // can be more than 2, this is not calculated, mongo stores this value internally
)
findQuery.exec(function(e, data) 
  console.log('found items', data); // will be 2 or less elements
);

【讨论】:

你能解释一下你所说的极限是什么意思吗? 想象一下,如果您的数据库中有 1000 个条目。你不想一次得到它们。我认为猫鼬也设置了某种默认限制。您想知道计数(在本例中为 1000),但可能只返回 50 个结果。如果您尝试计算响应的长度,您将得到 50。 此外,如果您想向用户显示结果并进行分页,您将使用限制。因此,如果每个页面有 50 个响应,您的第三页结果可能会这样查询:query.skip(100).limit(50) 您跳过前 2x50 并显示第三批 50 个结果。【参考方案3】:

正如猫鼬文档和本杰明的回答中所述,不推荐使用 Model.count() 方法。替代使用 count() 的方法如下:

  SomeModel.countDocuments(, function(err, count) 
    if (err)  return handleError(err)  //handle possible errors
    console.log(count)
    //and do some other fancy stuff
)

SomeModel
.estimatedDocumentCount()
.then(count => 
    console.log(count)
    //and do one super neat trick
)
.catch(err => 
    //handle possible errors
)

【讨论】:

【参考方案4】:

您也可以使用mongoose-paginate plugin。

例如:

Model.paginate(,  offset: 100, limit: 0 ).then(function(result) 
      // result.docs - Array of documents
      // result.total - Total number of documents in collection that match a query
      // result.limit - 0
      // result.offset - 100
);

【讨论】:

【参考方案5】:

DeprecationWarning:collection.count 已弃用,将在未来版本中删除。请改用 Collection.countDocuments 或 Collection.estimatedDocumentCount。 希望此更新对某人有所帮助。 示例:

var user = await User.find().countDocuments()

【讨论】:

以上是关于使用 Mongoose 查找和计数集合元素的主要内容,如果未能解决你的问题,请参考以下文章

在 mongoose 中使用查找填充一个集合

Mongoose - 如何聚合两个集合中的内容

mongoose listCollections()不返回集合名称,而是返回一个promise挂起

如何使用另一个集合 mongoose 查找子查询文档

mongoose 模型连接到 mongoDB

mongoose 模型连接到 mongoDB