【问题标题】:Avoid Aggregate 16MB Limit避免聚合 16MB 限制
【发布时间】:2017-12-26 01:33:44
【问题描述】:

我收集了大约 100 万份文档。每个文档都有internalNumber 属性,我需要在我的node.js 代码中获取所有internalNumbers。

以前我用的是

db.docs.distinct("internalNumber")

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

在节点中。

但随着集合的增长,我开始收到错误: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 中我得到一个错误:"MongoError: aggregation result exceeds maximum document size (16MB) at Function.MongoError.create"

请帮助克服这个限制。

【问题讨论】:

    标签: node.js mongodb aggregation-framework


    【解决方案1】:

    对于 Casbah 用户:

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

    【讨论】:

      【解决方案2】:

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

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

      let cursor = collection.aggregate(
        [{ "$group": { "_id": "$internalNumber" } }],
        { "cursor": { "batchSize": 500 } }
      );
      
      cursor.toArray((err,docs) => {
         // work with resuls
      });
      

      然后您可以使用像.toArray() 这样的常规方法将结果制作成在“客户端”上不具有相同限制的 JavaScript 数组,或者使用其他方法来迭代 "cursor"

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-08-18
        • 1970-01-01
        • 2017-05-15
        • 2013-12-29
        • 1970-01-01
        • 2018-09-11
        相关资源
        最近更新 更多