mongo深入理解-聚合操作

有可能我们需要对存入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的使用可能并不会很多, 以后继续完善。