根据 mongodb node driver docs 聚合函数现在返回一个游标(从 2.6 开始)。
我希望我可以使用它来获取预先限制和跳过的项目数,但在创建的游标上似乎没有任何计数功能。如果我在 mongo shell 中运行相同的查询,光标有一个 itcount 函数,我可以调用它来获取我想要的。
我看到创建的游标有一个 on data 事件(这是否意味着它是 CursorStream ?)它似乎被触发了预期的次数,但是如果我将它与 cursor.get 结合使用,则没有结果被传递到回调函数中.
新的游标功能可以用于统计聚合查询吗?
编辑代码:
在 mongo shell 中:
> db.SentMessages.find({Type : 'Foo'})
{ "_id" : ObjectId("53ea19af9834184ad6d3675a"), "Name" : "123", "Type" : "Foo" }
{ "_id" : ObjectId("53ea19dd9834184ad6d3675c"), "Name" : "789", "Type" : "Foo" }
{ "_id" : ObjectId("53ea19d29834184ad6d3675b"), "Name" : "456", "Type" : "Foo" }
> db.SentMessages.find({Type : 'Foo'}).count()
3
> db.SentMessages.find({Type : 'Foo'}).limit(1)
{ "_id" : ObjectId("53ea19af9834184ad6d3675a"), "Name" : "123", "Type" : "Foo" }
> db.SentMessages.find({Type : 'Foo'}).limit(1).count();
3
> db.SentMessages.aggregate([ { $match : { Type : 'Foo'}} ])
{ "_id" : ObjectId("53ea19af9834184ad6d3675a"), "Name" : "123", "Type" : "Foo" }
{ "_id" : ObjectId("53ea19dd9834184ad6d3675c"), "Name" : "789", "Type" : "Foo" }
{ "_id" : ObjectId("53ea19d29834184ad6d3675b"), "Name" : "456", "Type" : "Foo" }
> db.SentMessages.aggregate([ { $match : { Type : 'Foo'}} ]).count()
2014-08-12T14:47:12.488+0100 TypeError: Object #<Object> has no method 'count'
> db.SentMessages.aggregate([ { $match : { Type : 'Foo'}} ]).itcount()
3
> db.SentMessages.aggregate([ { $match : { Type : 'Foo'}}, {$limit : 1} ])
{ "_id" : ObjectId("53ea19af9834184ad6d3675a"), "Name" : "123", "Type" : "Foo" }
> db.SentMessages.aggregate([ { $match : { Type : 'Foo'}}, {$limit : 1} ]).itcount()
1
> exit
bye
在 Node 中:
var cursor = collection.aggregate([ { $match : { Type : 'Foo'}}, {$limit : 1} ], { cursor : {}});
cursor.get(function(err, res){
// res is as expected (1 doc)
});
cursor.count() 不存在
cursor.itcount() 不存在
on data 事件存在:
cursor.on('data', function(){
totalItems++;
});
但是当与 cursor.get 结合使用时,.get 回调函数现在包含 0 个文档
编辑 2:返回的光标似乎是 aggregation cursor 而不是文档中列出的光标之一
最佳答案
对于那些可能会搜索此内容的人来说,这可能值得一个完整的解释,因此为后代添加一个。
具体返回的是 node.js 的事件流,它有效地包装了 stream.Readable接口(interface)与几个方便的方法。一个 .count()
目前不是其中之一,考虑到当前使用的界面没有多大意义。
类似于 .stream()
返回的结果可用于游标对象的方法,当您考虑实现时,“计数”在这里没有多大意义,因为它旨在作为“流”进行处理,最终您将到达“结束”,否则只想处理直到到达那里。
如果您考虑过驱动程序中的标准“Cursor”接口(interface),则聚合游标不相同的原因有很多:
.sort()
的类别, .limit()
和 .skip()
.所有这些实际上在管道中指定的聚合框架中都有对应的指令。作为可能出现在“任何地方”而不仅仅是作为简单查询的后处理选项的管道阶段,提供相同的“光标”处理没有多大意义。 .hint()
, .min()
和 .max()
这是对“索引选择”和处理的更改。虽然这些可能对聚合管道有用,但目前没有简单的方法将它们包含在查询选择中。大多数情况下,上一点的逻辑会覆盖对“光标”使用相同类型接口(interface)的任何点。 其他考虑因素是您实际想要用游标做什么以及为什么“想要”返回一个游标。由于游标通常是“单程旅行”,因为它们通常只被处理直到到达终点并且在可用的“批次”中,因此可以得出合理的结论,即“计数”实际上只是在末尾,当实际上“队列”最终耗尽时。
虽然事实上标准的“光标”实现确实有一些技巧,但主要原因是这只是扩展了“元”数据概念,因为查询分析引擎必须“扫描”一定数量的文档才能确定哪个在结果中返回的项目。
不过,聚合框架稍微利用了这个概念。因为不仅有与通过标准查询分析器处理的结果相同的结果,而且还有额外的阶段。这些阶段中的任何一个都有可能“修改”实际在要处理的“流”中返回的结果“计数”。
同样,如果您想从学术的 Angular 来看这一点,并说“当然,查询引擎应该保留计数的‘元数据’,但我们可以不跟踪之后修改的内容吗?”。这将是一个公平的论点,管道运营商如
$match
和 $group
或 $unwind
甚至可能包括 $project
和新的 $redact
,所有这些都可以被认为是一个合理的案例,用于在每个管道阶段保持自己对“处理的文档”的跟踪,并在可能返回的“元数据”中更新它以解释完整的管道结果计数。最后一个论点是合理的,但也要考虑到目前为聚合管道结果实现“游标”概念是 MongoDB 的一个新概念。可以公平地说,在第一个设计点的所有“合理”期望都是组合文档的“大多数”结果不会限制 BSON 限制的大小。但随着使用范围的扩大,人们的看法会发生变化,事情也会发生变化以适应。
所以这个“可能”可能会改变,但这不是“当前”实现的方式。虽然
.count()
在标准游标实现上可以访问记录扫描数字的“元数据”,当前实现上的任何方法都将导致检索所有游标结果,就像 .itcount()
一样。在 shell 中。通过计算“数据”事件并在最后发出一些东西(可能是 JSON 流生成器)作为“计数”来处理“光标”项目。对于任何需要“预先”计数的用例,无论如何它似乎都不是游标的有效用途,因为输出肯定是一个合理大小的整个文档。
关于javascript - Mongo 聚合游标和计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25239408/