避免总计16MB的限制
我有一个约1M文件的集合。 每个文档都有internalNumber
属性,我需要在我的node.js代码中获得所有的internalNumber
。
以前我在用
db.docs.distinct("internalNumber")
要么
collection.distinct('internalNumber', {}, {},(err, result) => { /* ... */ })
在节点。
但随着collections的增长,我开始得到这样的错误: distinct is too big, 16m cap
。
现在我想要使用聚合。 它消耗了大量的内存,而且速度很慢,但是这样可以,因为我只需要在脚本启动时只执行一次。 我已经尝试过Robo 3T GUI工具:
db.docs.aggregate([{$group: {_id: '$internalNumber'} }]);
它的工作原理,我想在node.js中使用它的代码如下:
collection.aggregate([{$group: {_id: '$internalNumber'} }], (err, docs) => { /* ... * });
但在节点中,我得到一个错误: "MongoError: aggregation result exceeds maximum document size (16MB) at Function.MongoError.create"
。
请帮助克服这个限制。
问题在于,本地驱动程序与shell方法在缺省情况下的工作方式不同,因为“shell”实际上是返回一个“游标”对象,本地驱动程序需要“明确”使用此选项。
如果没有“游标”, .aggregate()
返回一个单一的BSON文档作为文档数组,所以我们把它转换成一个游标来避免这个限制:
let cursor = collection.aggregate( [{ "$group": { "_id": "$internalNumber" } }], { "cursor": { "batchSize": 500 } } ); cursor.toArray((err,docs) => { // work with resuls });
然后,您可以使用像.toArray()
这样的常规方法将结果生成为“客户端”上不具有相同限制的JavaScript数组,或用于迭代“游标”的其他方法。
对于Casbah用户:
val pipeline = ... collection.aggregate(pipeline, AggregationOptions(batchSize = 500, outputMode = AggregationOptions.CURSOR)