Mongo聚合光标&数数

时间:2014-08-11 08:58:46

标签: javascript node.js mongodb mongodb-query

根据mongodb node driver docs,聚合函数现在返回一个游标(从2.6开始)。

我希望我可以使用它来获得预先限制的物品数量。跳过但是在创建的光标上似乎没有任何计数功能。如果我在mongo shell中运行相同的查询,则游标会有一个itcount函数,我可以调用它来获取我想要的内容。

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

新光标功能是否可用于计算聚合查询?

编辑代码:

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

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

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

编辑2:返回的光标似乎是aggregation cursor而不是文档中列出的其中一个光标

1 个答案:

答案 0 :(得分:15)

对于那些可能会搜索此内容的人来说,这可能值得一个完整的解释,因此为后代添加一个。

具体来说,返回的是node.js的事件流,它有效地包含了stream.Readable接口的一些便利方法。目前,.count()不是其中之一,并且考虑到当前使用的界面没有多大意义。

类似于从光标对象可用的.stream()方法返回的结果,&#34; count&#34;当你考虑实现时,在这里没有多大意义,因为它意味着要作为一个&#34;流&#34;最终你将到达&#34;结束&#34;但在其他地方只是想要处理直到到达那里。

如果您考虑过标准&#34;光标&#34;来自驱动程序的接口,有一些可靠的原因,为什么聚合游标不一样:

  1. 游标允许&#34;修饰符&#34;在执行之前要处理的动作。这些属于.sort().limit().skip()的类别。所有这些实际上都在汇编框架中具有在管道中指定的对应指令。作为可能出现的管道阶段&#34;任何地方&#34;而不仅仅是作为简单查询的后处理选项,提供相同的&#34;游标&#34;这没有多大意义。处理

  2. 其他光标修饰符包括.hint().min().max()之类的特殊内容,它们是对索引选择的修改&#34;和处理。虽然这些可用于聚合管道,但目前没有简单的方法将它们包括在查询选择中。大多数情况下,前一点的逻辑覆盖了对&#34; Cursor&#34;使用相同类型的接口的任何要点。

  3. 其他考虑因素是你实际想要用光标做什么以及为什么你想要&#34;一个回来了。由于光标通常是单程旅行&#34;从某种意义上说,它们通常只有在达到目的结束时才会被处理,并且在可用的批量生产中,然后它会得出一个合理的结论:&#34;计数&#34;实际上到了最后,实际上是&#34; queue&#34;终于耗尽了。

    事实上,标准&#34;光标&#34;实现有一些技巧,主要原因是这只是扩展了一个&#34; meta&#34;数据概念作为查询分析引擎必须&#34;扫描&#34;一定数量的文件,以确定在结果中返回哪些项目。

    聚合框架虽然有点用这个概念。由于不仅存在与通过标准查询分析器处理的结果相同的结果,而且还有其他阶段。任何这些阶段都有可能修改&#34;结果&#34;计数&#34;实际上会在&#34; stream&#34;中返回待处理。

    同样,如果你想从学术的角度来看待这一点,并且说'&#34;当然,查询引擎应该保留“元数据”。对于计数,但我们不能跟踪之后修改的内容吗?&#34;。这将是一个公平的论证,而$match$group$unwind甚至可能包括$project和新$redact等管道运营商都可以被认为是一个合理的案例,可以自行跟踪所处理的文件&#34;在每个管道阶段并更新&#34;元数据&#34;可能会返回以解释完整的管道结果计数。

    最后一个论点是合理的,但也要考虑到目前实现一个&#34; Cursor&#34;聚合管道结果的概念是MongoDB的一个新概念。可以说,所有的合理的&#34;在第一个设计点的期望是&#34;大多数&#34;合并文件的结果不会对BSON限制造成限制。但随着使用范围的扩大,感知会发生变化,情况会发生变化以适应。

    所以这&#34;可以&#34;可能会改变,但它不是如何&#34;目前&#34;实现。虽然标准游标实现上的.count()可以访问&#34;元数据&#34;在记录扫描号码的地方,当前实现的任何方法都会导致检索所有游标结果,就像.itcount()在shell中一样。

    处理&#34;光标&#34;通过计算&#34;数据&#34;事件并发出一些东西(可能是一个JSON流生成器)作为&#34; count&#34;在末尾。对于任何需要计算&#34;前期&#34;它似乎不是一个有效的游标用途,因为肯定输出将是一个合理大小的整个文档。