如何在不超过最大文档大小的情况下编写聚合?
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
选项,但是还是不行以上是关于如何在不超过最大文档大小的情况下编写聚合?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不创建新输入信号的情况下编写具有多个输入的多路复用器?
如何在不使用已弃用的类的情况下编写 Hadoop map reduce 作业?