当前位置: 首页 > 知识库问答 >
问题:

为什么我在Spring Data Mongo中得到聚合异常,而在Mongo shell中没有?

章晗日
2023-03-14

我有一个在MongoDB Shell中工作的查询,但是当我增加要返回的文档数量时,它使用Spring Data MongoDB抛出聚合结果超过最大文档大小(16MB)异常。

以下是返回无误的shell查询:

db.myCollection.aggregate([{"$skip":0},{"$limit":10000},{"$match":{"_id"="550b2552e4b03562d6329a39"}}], {"allowDiskUse":true})

以下是Spring数据片段:

List<AggregrationOperation> ops = new ArrayList<AggregationOperation>();
ops.add(new SkipOperation(0));
ops.add(new LimitOperation(10000));
ops.add(new MatchOperation(Criteria.where("_id").is("550b2552e4b03562d6329a39")));

TypeAggregation<MyCollection> aggregation = Aggregation.newAggregation(MyCollection.class, ops).withOptions(Aggregation.newAggregationOptions().allowDiskUse(true).build());

AggregationResults<MyCollection> result = mongoTemplate.aggregate(aggregation, MyCollection.class);
List<MyCollection> myResults = result.getMappedResults()

当我限制在100或1000条记录时,一切正常。当我增加到10000时,会出现“聚合结果超过最大文档大小(16MB)”异常。

以下是我使用的版本供参考:

MongoDB = 3.0.0
Mongo Java Driver = 2.13.0
Spring Data MongoDB = 1.6.0
Spring Data Commons = 1.9.0

更新:

背景:我使用聚合解决方案是因为我在使用find()时超过了32MB的排序限制。我知道添加索引可以解决这个问题。不幸的是,此解决方案无法扩展。我想对列表网格中的所有列进行排序,这意味着需要索引10列。当然,在UI中,我可以将排序限制为特定列,但我再次尝试避免这种解决方案,这也是我尝试聚合的原因。

看来使用光标是我唯一的解决办法。有人能确认Spring Data MongoDB不提供直接游标支持吗?这意味着我必须使用MongoDB的应用编程接口?

共有2个答案

吕新
2023-03-14

默认情况下,您可以使用outputMode(AggregationOptions.outputMode.CURSOR)作为输出选项,而不是有限的16MB文档。请参阅聚合游标用法。

Aggregation.newAggregationOptions().outputMode(AggregationOptions.OutputMode.CURSOR).allowDiskUse(true).build()
邹华皓
2023-03-14

我使用RoboMongo(mongo客户端)也有同样的问题。尝试使用db.run命令()而不是

在某些客户机上使用聚合方法似乎会向查询中添加一些数据,而allowDiskUse将被忽略。

当我使用ranCommand时,它工作得很好:

db.runCommand(
   { aggregate: "collection_name",
     pipeline: [
            {$group: ...}, 
            {$match: ...},
            {$group: ...}
           ],
     allowDiskUse: true
   }

 类似资料:
  • 我使用Gson Library 2.8.0将JSON字符串转换为Java Hashmap,Maven作为构建系统,Tomcat作为WebApp运行我的代码。IDE:IntelliJ Idea 问题是每当我运行我的代码,执行停止和抛出类NotFound异常。 代码==>

  • 问题内容: 我知道静态方法在类级别。因此,我知道我不需要创建实例来调用静态方法。但我也知道我可以将静态方法(如LIKE)称为实例方法。这是我感到困惑的地方,因为我期望从null对象调用静态方法(就像在调用实例方法中一样)。我真的很感谢一些解释,为什么我错了一个期望。 这是示例代码: 问题答案: 通过实例调用静态方法不需要实例存在。只要编译器能够确定变量的类型,它就可以在评估表达式并丢弃结果后静态进

  • 我编写了这段代码,将整个以10为基数的数字转换成二进制。我相信代码就是它所需要的一切,但我无法让工作。 我在这个网站和其他网站上花了几个小时,尝试了无数次的修改,但都没有用。 我已经让代码无错误地编译,但一旦我运行它并输入程序就会崩溃。 下面是代码: 这些是java在我输入数字时抛出的异常。 我希望这是足够的信息。

  • 我正在学习“放心框架”。 我使用http://ziptasticapi.com免费的API为我的演习。 当我打电话: 我得到以下字符串: {“国家”:“美国”、“州”:“正义与发展党”、“城市”:“阿达克”} as响应字符串值。 当我尝试时: 我突然想到: JAVAlang.IllegalStateException:无法分析对象,因为响应中未指定支持的内容类型。内容类型为“文本/html”;字符

  • 问题内容: 我使用ES v 1.7。ES仅在“命中”部分返回_score,但是我对“命中”不感兴趣,我需要 使用_score 从响应的“聚合”部分中 获取数据 。为什么ES会喜欢这样,以及如何解决? Requset: 响应: 问题答案: 由于您正在使用排序,因此您需要为要计算的分数显式设置“ track_scores ”。 例:

  • 问题内容: 注意:我知道该方法。 在下面的代码示例中,我不明白为什么在方法抛出,但不是在方法。 问题答案: 原因如下:正如中所说: 此类的迭代器和方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间以任何方式对列表进行结构修改,除非通过迭代器自己的remove或add方法,否则迭代器将抛出。 该检查是在迭代器的方法中完成的(如你在stacktrace中所看到的)。但是,next()只有在传递