如何在不超过最大文档大小的情况下编写聚合?

Posted

技术标签:

【中文标题】如何在不超过最大文档大小的情况下编写聚合?【英文标题】:How could I write aggregation without exceeds maximum document size? 【发布时间】:2015-06-21 01:56:42 【问题描述】:

我通过如下查询得到exceeds maximum document size problem异常,

pipe = [
    "$match":  "birthday":"$gte":datetime.datetime(1987, 1, 1, 0, 0) 
    ]
res =db.patients.aggregate(pipe,allowDiskUse=True)

我通过添加 $project 运算符来修复它,

但是,即使我使用$project,文件仍然超过16MB 怎么办?

我能做什么?任何想法 ?谢谢

pipe = [
    "$project": "birthday":1, "id":1
    ,
    "$match":  "birthday":"$gte":datetime.datetime(1987, 1, 1, 0, 0) 
     
    ]
res =db.patients.aggregate(pipe,allowDiskUse=True)

异常

OperationFailure: command SON([('aggregate', 'patients'), ('pipeline', ['$match': 'birthday': '$gte': datetime.datetime(1987, 1, 1, 0, 0)]), ('allowDiskUse', True)]) on namespace tw_insurance_security_development.$cmd failed: exception: aggregation result exceeds maximum document size (16MB)

【问题讨论】:

【参考方案1】:

默认情况下,聚合结果在单个 BSON 文档中返回给您,这是大小限制的来源。如果您需要返回更多,您可以:

将结果输出到集合中。为此,您可以使用

完成管道

"$out": "some-collection-name"

然后您可以正常查询该集合(完成后您需要自己删除它)

通过在调用聚合时指定useCursor=True 将结果作为游标返回。

这两个选项都需要 mongodb 2.6:如果您仍在运行 mongodb 2.4,那么这只是聚合的基本限制。

【讨论】:

你会这么好心并给出一个小的Java示例或至少一个源代码吗?最佳 抱歉 - 我不熟悉 Java mongo API 感谢您的快速响应。我找到了一个解决方案(使用 spring 数据和 mongoDB):List<DBObject> pipeline = new ArrayList<>(); DBObject someMatchCriteria = new BasicDBObject(); someMatchCriteria.put("param", "value"); DBObject out = new BasicDBObject(); out.put("$out", "outCollectionName"); pipeline.add(new BasicDBObject("$match", someMatchCriteria)); pipeline.add(out); mongoOperations.getCollection("inCollectionName").aggregate(pipeline);【参考方案2】:

正如@Frederick 所说,至少需要 mongo 2.6,为了进一步参考,here 是来自 mongo 文档的链接,其工作方式类似于 runCommand 方式,但使用 db.collection.aggreagate,请注意,对于文档限制,请使用“光标”选项,排序限制使用“allowDiskUse”选项。

【讨论】:

【参考方案3】:

您可以使用aggregateCursor(collection_name, $pipeLine, ["useCursor" => true])

pipe = [
    "$match":  "birthday":"$gte":datetime.datetime(1987, 1, 1, 0, 0) 
    ]
res =db.patients.aggregateCursor(collection_name, pipe, ["useCursor" => true]);
        
$ret = [];

foreach ($taskList as $task)
  array_push($ret, $task);

        
return $ret;

【讨论】:

【参考方案4】:

使用下面的sn -p

db.patients.runCommand('aggregate', 
        pipeline: [
    "$project": "birthday":1, "id":1,
    "$match":  "birthday":"$gte":datetime.datetime(1987, 1, 1, 0, 0) 
], 
        allowDiskUse: true)

此处的 allowDiskUse 将有助于找出超过 16 MB 的数据

【讨论】:

其实我已经启用了allowDiskUse选项,但是还是不行

以上是关于如何在不超过最大文档大小的情况下编写聚合?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不重复自己的情况下编写三元运算符(又名 if)表达式

如何在不创建新输入信号的情况下编写具有多个输入的多路复用器?

如何在不使用已弃用的类的情况下编写 Hadoop map reduce 作业?

你好!无论如何要在不使用联合的情况下编写类似的查询吗?

如何在不使用flutter_test.dart包的情况下编写用于在flutter集成测试中点击屏幕点的测试脚本?

在不违反 SRP、OCP、DRY 的情况下编写测试