MongoDB聚合比较:group()、$group和MapReduce

39
我有些困惑何时该使用group()、aggregate或$group。我阅读了网站http://www.mongodb.org/display/DOCS/Aggregation上的group()文档,以及$group的文档。只有在分片的情况下,group()才无法使用吗?此外,我有这种感觉,$group比group()更强大,因为它可以与聚合框架中的其他管道操作符一起使用。$group如何与mapreduce相比?我从某个地方读到,$group不会生成任何临时集合,而mapreduce则会。是这样吗?
有人能否提供一个示例或引导我到一个链接,将这三个概念一起解释,使用相同的示例数据,以便我可以轻松比较它们?

编辑:
自2.2版本发布以来,这些命令是否有任何新变化?

1
讲解得非常清楚...可以帮助的链接是.... https://groups.google.com/forum/?fromgroups=#!topic/mongodb-user/rYlBfqpybpY - Danish
1
@user2157221 不错的发现,从 Google Groups 的讨论中可以强调几点:(1) 聚合框架可以使用索引来降低操作成本,在你只对集合的部分内容感兴趣时;(2) "等价的聚合框架比 MR 快了 7 倍。"(3)“使用map reduce时,通常会输出到一个集合(通常是临时集合)。当你实际想要将数据直接返回给一个调用库时,聚合框架更适合。” - zamnuts
1个回答

76

由于名称相似,可能会有点混淆,但是命令 group() 与聚合框架中的 $group 管道操作符 是不同的功能和实现。

aggregation features(聚合特性)是 MongoDB 的 group() 命令、聚合框架和 MapReduce。它们之间存在一些重叠,但我将尝试解释每个功能的差异和限制,截至 MongoDB 2.2.0 版本。

注意:inline result sets(内联结果集)是指在内存中处理并在函数调用结束时返回结果的查询。可选的输出选项(目前仅适用于 MapReduce)包括将结果保存到新的或现有的集合中。

group() 命令

  • 简单的语法和分组功能,类似于 SQL 中的 GROUP BY

  • 以内联方式返回结果集(作为分组项目的数组)。

  • 使用 JavaScript 引擎实现;可以编写自定义的 JavaScript reduce() 函数。

  • 当前限制

    • 不能将结果分组到具有超过 20,000 个键的结果集中。

    • 结果必须符合 BSON 文档的限制(目前为 16MB)。

    • 执行时会占用读锁,并且不允许其他线程执行 JavaScript。

    • 不能与分片集合一起使用。

  • 另请参见:group() 命令示例

MapReduce

  • 实现了MapReduce模型以处理大型数据集。

  • 可以从多种输出选项(inline, new collection, merge, replace, reduce)中进行选择。

  • MapReduce函数使用JavaScript编写。

  • 支持非分片和分片输入集合。

  • 可用于对大集合进行增量聚合。

  • MongoDB 2.2实现了更好的支持分片映射减少输出

  • 当前限制

    • 单个emit只能容纳MongoDB最大BSON文档大小(16MB)的一半。

    • 存在JavaScript锁,因此mongod服务器一次只能执行一个JavaScript函数..但是,MapReduce的大多数步骤非常短,因此锁定可以频繁地放弃。

    • MapReduce函数可能难以调试。您可以在mongod日志中使用print()printjson()来包含诊断输出。

    • MapReduce通常对试图将关系查询聚合经验转换为编程人员来说并不直观。

  • 另请参阅:Map/Reduce示例

聚合框架

  • MongoDB 2.2.0生产版本(2012年8月)的新功能。

  • 针对改进性能和可用性的特定目标设计。

  • 返回内嵌结果集。

  • 支持非分片和分片输入集合。

  • 采用“管道”方法,在通过一系列管道操作符(如匹配、投影、排序和分组)时转换对象。

  • 管道操作符不需要为每个输入文档生成一个输出文档:操作符也可以生成新的文档或过滤掉文档。

  • 使用投影,您可以添加计算字段,创建新的虚拟子对象,并将子字段提取到结果的顶层。

  • 管道操作符可以根据需要重复使用(例如,多个$project$group步骤)。

  • 当前限制

    • 结果会以内联方式返回,因此仅限于服务器支持的最大文档大小(16MB)

    • 不支持与MapReduce相同数量的输出选项

    • 受聚合框架支持的操作符和表达式限制(即无法编写自定义函数)

    • 聚合的最新服务器功能,因此在文档、功能集和用法方面有更大的成熟空间。

  • 另请参见:聚合框架示例

  • 有人能够给我展示一个例子或将这三个概念解释在一起的链接,使用相同的样本数据,以便我可以轻松地进行比较吗?

    通常不会找到有用于比较所有三种方法的示例,但是以下是以前的StackOverflow问题,展示了不同的变化:


    @Stennie 关于MapReduce(来自文档),(1)在map函数中,“一个emit只能容纳MongoDB最大BSON文档大小的一半”,因此,MapReduce具有与$groupgroup()类似的“数据大小”限制;请参见http://docs.mongodb.org/manual/reference/method/db.collection.mapReduce/#requirements-for-the-map-function。 (2)mongodb> = 2.4允许并发JavaScript操作,而旧版本在单个线程中执行代码;请参见http://docs.mongodb.org/manual/core/map-reduce/#concurrency - zamnuts
    3
    如上所述,这个答案最初是针对MongoDB 2.2.0(当时的当前版本)编写的。自那以后有许多改进,因此我建议查阅最新文档以获取准确信息,包括聚合命令比较(该命令是受这个答案启发的!)。MongoDB 2.4具有更好的JavaScript并发性能,改进的聚合框架性能以及新的聚合管道操作符,如$geoNear(地理空间匹配)。 - Stennie

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接