第七章 聚合

如果你有数据存储在MongoDB中,你想做的可能就不仅仅是将数据提取出来这么简单了。你可能希望对数据进行分析并加以利用。本章介绍MongoDB提供的聚合工具:
  • 聚合框架
  • MapReduce
  • 几个简单聚合命令:count、distinct、group

7.1 聚合框架

使用聚合框架可以对集合中的文档进行变换和组合。基本上,可以用多个构件创建一个管道,用于对一连串的文档进行处理,这些构建包括筛选、投射、分组、排序、限制、跳过。

例如,有一个保存杂志的文章集合,你可能希望找出发表文章最多的那个作者,假设每篇文章被保存为MongoDB中的一个文档,可以按照如下步骤创建管道:
  • 1、将每个文章文档中的作则投射出来
  • 2、将作者按照名字排序,统计每个名字出现的次数。
  • 3、将作者名字出现的次数的降序顺序
  • 4、返回结果限制为前5个

这里的每一步都对应聚合框架中的一个操作符:

#1、
{"$project":{"author":1}}
    这样可以将"author"投射出来。

#2、
{"$group":{"_id":"%author","count":{"$sum":1}}}

#3、
{"$sort":{"count":1}}

#4、
{"$limit":5}

再MongoDB中实际运行时,要将这些操作分别传给aggregate()函数

7.2 管道操作符

每个操作符都会接受一连串的文档,对这些文档做一些类型转换,最后将转换后的文档作为结果传递给下一个操作符。

不同的管道操作符可以按任意顺序组合在一起,而且可以被重复任意次。

7.2.1 $match

$match 用于对文档集合进行筛选,之后就可以在筛选得到的文档子集上做聚合。

7.2.2 $project

使用$project可以从文档中提取字段。可以重命名字段,还可以在这些字段上济宁一些有意思的操作。

7.2.3 $group

$group操作符可以将文档依据特定字段的的不同值进行分组。

7.2.4 $unwind

拆分(unwind) 可以将数组中的每一个值拆分为单独的文档。

7.2.5 $sort

可以根据任意字段(或者多个字段)进行排序,在普通查询中的语法相同。

7.2.6 $limit

$limit会接受一个数字n,返回结果集中的前n个文档。

7.2.8 使用管道

应该尽量在管道的开始阶段就将尽可能多的文档和字段过滤掉。管道如果不是直接从原先的集合中使用数据,那就无法再筛选和排序中使用索引。

MongoDB不允许单一的聚合操作暂用过多的系统内存:如果MongoDB发现某个聚合操作占用20%以上的内存,这个操作就会直接输出错误。

7.3 MapReduce

用MapReduce开解决这个问题有点大材小用了。不过还是一种了解其机制的不错的方式。

7.3.2 示例2:网页分类

假设有个网站,人们可以提交其他网页的链接,比如reddit。提交者可以给这个链接添加标签,表明主题,比如politice、geek或者icanhascheezburger。可以用MapReduce找出哪个主题最为热门。热门与否由最近的投票决定。

7.3.3 MongoDB和MapReduce

7.4 聚合命令

MongoDB为在集合上执行基本的聚合任务提供了一些命令。然而,复杂的group操作可能仍然需要JavaScript、count和distinct操作可以被简化为普通命令,不需要使用聚合框架。

7.4.1 count

count是最简单的聚合工具,用于返回集合中的文档数量。

也可以给count传递一个查询文档,Mongo会计算查询结果的数量。

7.4.2 distinct

distinct用来找出给定键的所有不同值,使用时必须指定集合和键。

7.4.3 group

使用group可以执行更复杂的聚合,先选定分组所依据的键,然后MongoDB就会将集合依据选定的键的不同值分成若干组。然后可以对每一个分组内的文档进行聚合,得到一个结果文档。

如果对您有用,请我喝杯咖啡吧。

赞助扫码::
../../../_images/apay.jpg ../../../_images/pay_wechat.png