Mongo聚合游标&计数

根据mongodb节点驱动文档 ,聚合函数现在返回一个游标(从2.6开始)。

我希望我可以用这个来获得项目数量的预先限制和跳过,但是在创build的游标上似乎没有任何计数function。 如果我在mongo shell中运行相同的查询,游标会有一个itcount函数,我可以调用它来获得我想要的。

我看到创build的游标有一个on数据事件(这是否意味着它是一个CursorStream ?)似乎会触发预期的次数,但如果我将它与cursor.get结合使用没有结果传递到callback函数。

新的游标function可以用来统计聚合查询吗?

编辑代码:

在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 

在节点中:

 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数据事件存在:

 cursor.on('data', function(){ totalItems++; }); 

但是当与cursor.get结合使用时,.getcallback函数现在包含0个文档

编辑2:返回的游标似乎是聚合游标,而不是文档中列出的游标之一

       

网上收集的解决方案 "Mongo聚合游标&计数"

对于那些可能寻找这个的人来说,这可能值得充分的解释,所以为后代添加一个。

具体来说,返回的是Node.js的事件stream,它可以有效地包装stream。可以使用几个方便的方法来实现可读接口。 .count()目前不是其中之一,考虑到目前使用的界面没有多大意义。

类似于游标对象可用的.stream()方法返回的结果,当考虑实现时,“count”在这里没有什么意义,因为它意味着作为一个“stream”来处理,最终你将要达到“结束”,否则只是想处理,直到到达那里。

如果您从驱动程序中考虑了标准的“光标”接口,那么为什么聚合游标不同:

  1. 游标允许在执行之前处理“修饰符”操作。 这些属于.sort() .limit().skip()类别。 所有这些实际上都有在pipe道中指定的聚合框架中的对应指令。 作为可能出现在“任何位置”的stream水线阶段,而不仅仅是作为简单查询的后处理选项,提供相同的“光标”处理没有多大意义。

  2. 其他游标修饰符包括特殊function,例如.hint().max() ,它们是“索引select”和处理的改变。 虽然这些可以用于聚合pipe道,但是目前还没有简单的方法将这些包括在查询select中。 大多数情况下,前一点的逻辑覆盖使用相同types的接口的任何点“光标”。

其他的考虑因素是你真正想用光标做什么,以及为什么你要“返回”。 由于游标通常是一种“单向游程”,通常只有在游戏到达终点时才进行处理,并在“批量”中使用,那么就可以得出一个合理的结论,即“计数”实际上到了最后,事实上,“排队”最终被耗尽。

虽然事实上标准的“游标”实现存在一些技巧,但其主要原因是这只是扩展了“元数据”概念,因为查询分析引擎必须“扫描”一定数量的文档以确定哪个项目返回结果。

汇总框架虽然略微使用了这个概念。 由于不仅有与通过标准查询分析器处理相同的结果,而且还有其他阶段。 任何这些阶段都有可能“修改”实际返回到“stream”中的结果“计数”以进行处理。

再一次,如果你想从学术的angular度来看待这个问题,并说:“当然,查询引擎应该保留”元数据“的数量,但我们不能追踪什么修改?”。 这是一个公平的论点,诸如$match$group$unwind类的pipe道操作符,甚至可能包括$project和new $redact ,都可以被认为是保持自己对“处理文档”在每个stream水线阶段,并更新可能返回的“元数据”来解释完整的stream水线结果计数。

最后一个论点是合理的,但是也要考虑到目前为聚合stream水线结果实施“光标”概念是MongoDB的一个新概念。 可以说,在第一个devise点上,所有“合理的”期望都可能是由于合并文件的“最”结果不会对BSON的限制产生限制。 但随着使用量的增加,感知被改变,事物也会改变以适应。

所以这个“可能”可能会被改变,但这不是“现在”实施的方式。 虽然标准游标实现上的.count()可以访问logging扫描号码的“元数据”,但是当前实现的任何方法都会导致检索所有的游标结果,就像.itcount()在贝壳。

通过对“data”事件进行计数来处理“游标”项,并在末尾发出一些(可能是JSONstream生成器)作为“count”。 对于任何需要“预先计数”的用例,无论如何,对于游标来说,这似乎都不是一个有效的用法,因为输出将是一个合理大小的整个文档。