MongoDB Aggregation

《Seven Database in Seven Weeks》提供了一个较好的数据实例:

那么最终生成的文档如下:

下面使用上面的文档来测试

统计得到的结果的数量

distinct()
distinct()命令返回了每条去重的匹配值(而非文档). 可以用下面的语句获得大于5550005的component号。
db.phones.distinct(‘components.number’, {‘components.number': { $lt : 5550005 } })
[ 5550000, 5550001, 5550002, 5550003, 5550004]
group()
gourp()聚合查询命令类似于SQL中的GROUP BY,这是一个非常复杂的操作:

http://docs.mongodb.org/manual/reference/method/db.collection.group/

db.collection.group{ key, reduce, initial, [keyf,] [cond,] [finalize] }
其参数功能如下:
key: 分组文档的字段。和keyf两者必须有一个
keyf: 指定一个javascript函数,用来动态确定文档的分组。
initial: 初始化聚合结果文档,即为reduce函数的赋一个初值
cond: Optional, 查询条件,相当于SQL group by语句中的where子句
reduce: 执行的reduce聚合函数,例如执行一个sum或者count操作。函数需要返回值。
finalize: Optional,在执行完成后对结果文档最终执行的函数。

db.phones.group({
initial: { count:0 },
reduce: function(phone, output) { output.count++; },
cond: { ‘components.number': { $gt : 5599999 } },
key: { ‘components.area’ : true }
})
[ { “components.area” : 855, “count” : 50000 } ]
由此可以看到,首先initial中,为变量count赋值0,聚合键为components.area,过滤条件components.number $gt 5599999。最终得到了这个结果。
同样可以实现sum的等聚合函数的统计,即设定initial,并在reduce函数进行必要的计算即可。
MapReduce
MongoDB中的mapreduce与hadoop map-reduce架构非常相似,将大规模的文档聚合查询成为想要的结果。Hadoop Hive把SQL解析成为Map-Reduce框架上的函数执行,同理MongoDB中的一些高级查询(distinct,group by等)也可以用MapReduce来实现,或者说group by等只是MapReduce的一个特例。(http://docs.mongodb.org/manual/core/map-reduce/
mr
在上面的map-reduce操作中,mongoDB在map阶段输入为经过查询条件过滤后的每一个文档,输出为一个key-value对。这些键对应了多个值,那么就需要后面的reduce阶段产生聚合结果(输出也是一个文档),而map函数和reduce函数都是自定义的javascript函数。
官方Docs提供了两个example:
http://docs.mongodb.org/manual/tutorial/map-reduce-examples/
http://docs.mongodb.org/manual/tutorial/perform-incremental-map-reduce/
在这里我尝试用MapReduce实现一下上面phones的聚合函数,其中,map函数输出以components.area为key,value为1表示1个文档,然后在reduce函数中执行一个sum就做到了group by的count效果。

聚合管道
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。这样,通过多级聚合指令可以得到最终想要的聚合结果。
pipe

Reference:
《MongoDB the definitive guide》
《Seven Database in Seven Weeks》
Mongo Docs

Posted in Database, JavaScript, NoSQL.