有可能我们需要对存入mongo的数据进行分析整理, 特别是爬虫获取到的元数据,这时候mongo的聚合操作(Aggregation)就给我们带来了很大的便利。 利用Mongo的这个特性, 我们可以很方便的对数据进行二次处理, 形成类似于Linux的管道操作(pipline)。Aggregation 直达链接
基本介绍
mongo的聚合操作主要有以下构成。
-
filtering
对集合内的文档进行过滤, 选择需要的文档
-
projecting
{"$project": {"name": 1}}, 语法有点类似于, 查询操作控制返回字段的形式, 通过1返回, 0进行抛弃。 -
grouping
{"$group": {"_id": "$name", "count": {"$sum": 1}}}这个语句完成的操作就是: 按名字分组, 并且没出现一次该名字, 就将文档内count字段的值加1
-
sorting
{"$sort": {"count": -1}}, 返回的结果俺count降序排列 -
limiting
{"$limit": 10}, 返回结果集中的前10条 -
skipping
{"$skip": 10}, 跳过结果集的前10个文档
db.student.aggregate(
{"$project": {"name": 1}},
{"$group": {"_id": "$name", "count": {"$sum": 1}}},
{"$sort": {"count": -1}},
{"$limit": 10}
)
aggregate() 通过一系列的操作, 完成了对文档的筛选, 及处理
管道操作符
每个管道操作符都会接受一系列文档, 并在处理之后传递给下一个管道操作符, 最后的操作符会返回结果。
管道符可以任意组合, 就像Linux中一样, 也可以多次使用。
$match
match 负责文档的过滤, 筛选出我们需要的文档, 这个操作应该放在最前面, 这样,不仅能够使用索引, 还能减少管道的工作量。
match几乎可以使用所有的查询操作符, 如$in, $lt….但是, 不能在match中使用地理位置操作符。
{$match: {"age": {"$lt": 30}}}, 如此就能筛选出小于30岁的人。
$project
project 除了能够制定返回的字段,还能进行重命名。比如将age重命名为old
{"$project": {"old": "$age", "age": 0}}, 此时, 文档就只会返回old字段
ps: 我们必须明确指定不返回age字段, 不然会返回两份数据, 当然利用这个特性,我们也可以做数据备份, 然后在其之上进行操作。
除了上面的简单操作, project通过表达式,可以完成一些更加复杂的操作
数学表达式
| 操作符 | 示例 | 说明 |
|---|---|---|
| $add | {“$add”: [expr1, expr2…]} | res = 1+2+3… |
| $subtract | {“$subtract”: [expr1, expr2]} | res = expr1-expr2 |
| $divide | {“$divide”: [expr1, expr2]} | res = expr1/expr2 |
| $multiply | {“$multiply”: [expr1, expr2….]} | res = 1×2×3…. |
| $mod | {“$mod”: [expr1, expr2]} | res = expr1%expr2 |
日期表达式
$year, $month, $week, $dayofMonth, $dayOfWeek, $dayOfYear, $hour, $minute, $second
示例: $project: {"interval": {"$subtract": [{"$year": new Date()}, {"year": "$hireDate"}]}
求出员工的工作年限。
字符串表达式
$substr, $concat, $toLower, $toUpper
逻辑表达式
- 比较
$cmp,$strcasecmp,$lt, …. - 布尔
$and,$or,$not - 分支
$cond,$ifNull
$group
group 操作与MySQL的group by 是非常相似的。
可以根据一个字段分组, 也可以是多个。
{"$group": {"_id": "$name"}}
{"$group": {"_id": {"name": "$name", "age": "$age"}}}
- 算数:
$add,$avg - 极值:
$max,$min,$last,$first - 数组:
$addToSet,$push
$unwind
这个操作符用来拆分文档中的数组元素, 使每个元素成为单独的文档返回
$sort
$limit
$skip
map-reduce
使用map-reduce能够完成更加复杂的操作, 但是map-reduce的速度确是最慢的, 所以不到万不得已,最好不要使用它。
map-reduce的使用可能并不会很多, 以后继续完善。