避免聚合16MB限制

时间:2017-07-20 11:21:51

标签: node.js mongodb aggregation-framework

我有大约1M文档的集合。每个文档都有internalNumber属性,我需要在node.js代码中获取所有internalNumber

以前我在使用

db.docs.distinct("internalNumber")

collection.distinct('internalNumber', {}, {},(err, result) => { /* ... */ })

在Node。

但随着收藏的增长,我开始收到错误:distinct is too big, 16m cap

现在我想使用聚合。它消耗大量内存并且速度很慢,但是没关系,因为我只需要在脚本启动时执行一次。我在Robo 3T GUI工具中尝试过:

db.docs.aggregate([{$group: {_id: '$internalNumber'} }]); 

它有效,我想在node.js代码中使用它,方法如下:

collection.aggregate([{$group: {_id: '$internalNumber'} }],
  (err, docs) => { /* ... * });

但在Node I中出现错误:"MongoError: aggregation result exceeds maximum document size (16MB) at Function.MongoError.create"

请帮助克服这个限制。

2 个答案:

答案 0 :(得分:3)

问题是本机驱动程序与默认情况下shell方法的工作方式不同,因为“shell”实际上返回了一个“游标”对象,本机驱动程序“明确地”需要此选项。

如果没有“游标”,.aggregate()会将单个BSON文档作为文档数组返回,因此我们将其转换为游标以避免限制:

let cursor = collection.aggregate(
  [{ "$group": { "_id": "$internalNumber" } }],
  { "cursor": { "batchSize": 500 } }
);

cursor.toArray((err,docs) => {
   // work with resuls
});

然后,您可以使用常规方法(如.toArray())将结果设置为“客户端”不具有相同限制的JavaScript数组,或其他用于迭代"cursor"的方法。

答案 1 :(得分:0)

对于Casbah用户:

val pipeline = ...
collection.aggregate(pipeline, AggregationOptions(batchSize = 500, outputMode = AggregationOptions.CURSOR)