前言
除了简单的根据条件查询之外,有时候需要聚合查询来应对复杂的查询功能。更多有关聚合查询的内容请参考Mongo聚合查询。
聚合管道
MongoDB的聚合框架是基于数据处理管道的概念建模的。文档进入一个多阶段管道,该管道将文档转换为聚合结果。例如:
db.orders.aggregate([
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])
第一阶段:$match阶段根据状态字段过滤文档,并将状态等于“A”的文档传递给下一阶段。
第二阶段:$group阶段根据cust_id字段对文档进行分组,以计算每个唯一的cust_id数量的总和。
最基本的管道阶段提供的过滤器操作类似于修改输出文档形式的查询和文档转换。
其他管道操作提供了按特定字段分组和排序文档的工具,以及聚合数组(包括文档数组)内容的工具。此外,管道阶段可以对计算平均值或连接字符串等任务使用操作符。
管道使用MongoDB中的本地操作提供有效的数据聚合,是MongoDB中数据聚合的首选方法。
聚合管道可以对分片集合进行操作。
在聚合管道的某些阶段,可以使用索引来提高其性能。此外,聚合管道有一个内部优化阶段。有关详细信息,请参见管道操作符、索引和聚合管道优化。
MapReduce
MongoDB还提供了mapreduce操作来执行聚合。通常,map-reduce操作有两个阶段:map阶段处理每个文档并为每个输入文档发出一个或多个对象,reduce阶段组合映射操作的输出。可选地,map-reduce可以有一个finalize阶段来对结果进行最终修改。与其他聚合操作一样,map-reduce可以指定查询条件来选择输入文档,并对结果进行排序和限制。
map-reduce使用定制的JavaScript函数来执行map和reduce操作,以及可选的finalize操作。与聚合管道相比,自定义JavaScript提供了很大的灵活性,但通常情况下,map-reduce的效率和复杂性都低于聚合管道。
Map-reduce可以对分片集合进行操作。Map-reduce操作还可以输出到分片集合。有关详细信息,请参见地图精简和分片集合。
从MongoDB 2.4开始,某些mongo shell函数和属性在map-reduce操作中是不可访问的。MongoDB 2.4还支持同时运行多个JavaScript操作。在MongoDB 2.4之前,JavaScript代码在一个线程中执行,这给map-reduce带来了并发问题。
单一的聚合操作
MongoDB还提供了db.collection.estimatedDocumentCount()、db.collection.count()和db.collection.distinct()。
所有这些操作都从单个集合聚合文档。虽然这些操作提供了对公共聚合流程的简单访问,但它们缺乏聚合管道和map-reduce的灵活性和能力。
附加特性和行为
有关聚合管道、map-reduce和特殊组功能的特性比较,请参见聚合命令比较。