javascript Mongo聚合游标和计数

hivapdat  于 2023-05-27  发布在  Java
关注(0)|答案(2)|浏览(120)

根据mongodb节点驱动文档,聚合函数现在返回一个游标(从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

在节点中:

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,而不是文档中列出的光标之一

waxmsbnn

waxmsbnn1#

这可能值得为那些可能寻找这一点的人提供一个完整的解释,因此为后代增加一个。
具体来说,返回的是node.js的Event Stream,它有效地 Package 了stream.Readable接口,并使用了几个方便的方法。.count()目前不是其中之一,考虑到当前使用的接口没有多大意义。
与游标对象可用的.stream()方法返回的结果类似,当您考虑实现时,“count”在这里没有太大意义,因为它意味着作为“流”进行处理,最终您将到达“结束”,但否则只想处理直到到达那里。
如果您考虑驱动程序的标准“Cursor”接口,则有一些可靠的原因可以解释为什么聚合游标不相同:
1.游标允许在执行之前处理“修改器”操作。它们属于.sort().limit().skip()的类别。所有这些实际上都在聚合框架中有对应的指令,这些指令在管道中指定。由于流水线阶段可以出现在“任何地方”,而不仅仅是作为简单查询的后处理选项,因此提供相同的“游标”处理没有多大意义。
1.其他游标修饰符包括特殊的.hint().min().max(),它们是对“索引选择”和处理的更改。虽然这些可能对聚合管道有用,但目前没有简单的方法将这些包括在查询选择中。大多数情况下,上一点的逻辑覆盖了使用相同类型接口的任何“光标”。
其他考虑因素是您实际上想用游标做什么以及为什么“希望”返回一个游标。由于游标通常是“单程旅行”,在这个意义上,它们通常只被处理,直到到达终点,并在可用的“批处理”,然后它作出合理的结论,“计数”实际上只是在终点,而事实上,“队列”最终耗尽。
虽然事实上标准的“游标”实现确实有一些技巧,但主要原因是这只是扩展了“ meta”数据概念,因为查询分析引擎必须“扫描”一定数量的文档,以便确定在结果中返回哪些项。
聚合框架稍微使用了这个概念。因为不仅有与通过标准查询分析器处理的相同的结果,而且还有额外的阶段。这些阶段中的任何一个都有可能“修改”实际上将在要处理的“流”中返回的结果“计数”。
同样,如果你想从学术的Angular 来看待这个问题,并说“当然,查询引擎应该保留' meta数据'用于计数,但我们可以不跟踪之后修改了什么吗?”“.这将是一个公平的论点,管道操作符,如$match$group$unwind,甚至可能包括$project和新的$redact,所有这些都可以被认为是在每个流水线阶段中保持它们自己的“处理的文档”的跟踪并在“ meta数据”中更新该跟踪的合理情况。其可能被返回以解释完整流水线结果计数。
最后一个论点是合理的,但也要考虑到,目前为聚合管道结果实现“游标”概念是MongoDB的新概念。可以合理地认为,在第一个设计点的所有“合理”预期都是来自组合文档的“大多数”结果的大小不会限制BSON限制。但随着使用范围的扩大,人们的看法也会发生变化,事物也会随之变化。
因此,这“可能”会改变,但它不是如何“目前”实施。虽然标准游标实现上的.count()可以访问记录扫描数字的“ meta数据”,但当前实现上的任何方法都将导致检索所有游标结果,就像.itcount()在shell中所做的那样。
通过计算“data”事件并在最后发出一些东西(可能是JSON流生成器)作为“count”来处理“cursor”项。对于任何需要“预先”计数的用例,无论如何,它看起来都不像是游标的有效用途,因为输出肯定是一个合理大小的整个文档。

bxpogfeg

bxpogfeg2#

您可以使用.toArray(),例如

// resultCursor from aggregation
var resultArray = resultCursor.toArray();
print(resultArray.length);

相关问题