MongoDB聚合篇

x33g5p2x  于2021-12-25 转载在 Go  
字(26.5k)|赞(0)|评价(0)|浏览(324)

MongoDB中聚合功能分为以下三种

  • 聚合框架agregate()
  • MapReduce
  • 聚合命令(count、distinct、group)

聚合框架agregate

使用聚合框架agregate可以通过多个操作符对文档进行处理,将前一个操作符处理后的结果传给下一个操作符,最后一个操作符处理的结果就是聚合的最后的结果

$match

筛选条件,过滤掉不满足条件的文档,可以使用常规的查询操作符,如gt、lt、$in等

> db.articles.find()
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "author" : "zhangsan", "title" : "Java Primer", "like" : 10 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "author" : "zhangsan", "title" : "iOS Primer", "like" : 30 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "author" : "zhangsan", "title" : "Android Primer", "like" : 20 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "author" : "lisi", "title" : "Html5 Primer", "like" : 40 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "author" : "lisi", "title" : "Go Primer", "like" : 30 }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "author" : "mengday", "title" : "Swift Primer", "like" : 8 }
>

// $match
> db.articles.aggregate( {"$match": {"like": {"$gte" : 10} }} )
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "author" : "zhangsan", "title" : "Java Primer", "like" : 10 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "author" : "zhangsan", "title" : "iOS Primer", "like" : 30 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "author" : "zhangsan", "title" : "Android Primer", "like" : 20 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "author" : "lisi", "title" : "Html5 Primer", "like" : 40 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "author" : "lisi", "title" : "Go Primer", "like" : 30 }

$project 投射

  • 用于包含、排除字段: 设置要查询或者要过滤掉的字段,0: 要过滤掉的字段,不显示,1:需要查询的字段
  • 对字段重命名,
  • 在投射中使用一些【表达式】:数学表达式、日期表达式、字符串表达式、逻辑表达式(比较表达式、布尔表达式、控制语句)
> db.articles.aggregate( {"$match": {"like": {"$gte" : 10} }}, {"$project": {"_id": 0, "author":1, "title": 1}} )
{ "author" : "zhangsan", "title" : "Java Primer" }
{ "author" : "zhangsan", "title" : "iOS Primer" }
{ "author" : "zhangsan", "title" : "Android Primer" }
{ "author" : "lisi", "title" : "Html5 Primer" }
{ "author" : "lisi", "title" : "Go Primer" }

// $project: 当字段的值是0或者1时用于过滤字段,当键是一个自定义的字符串,值为$跟上原来的字段,表示要对该字段进行重命名
> db.articles.aggregate( {"$match": {"like": {"$gte" : 10} }}, {"$project": {"_id": 0, "author":1, "Book Name": "$title"}} )
{ "author" : "zhangsan", "Book Name" : "Java Primer" }
{ "author" : "zhangsan", "Book Name" : "iOS Primer" }
{ "author" : "zhangsan", "Book Name" : "Android Primer" }
{ "author" : "lisi", "Book Name" : "Html5 Primer" }
{ "author" : "lisi", "Book Name" : "Go Primer" }
>

// 通过修改字段的名称来达到生成一个字段的副本,以便在后面的操作符中使用
> db.articles.aggregate( {"$match": {"like": {"$gte" : 10} }}, {"$project": {"ID":"$_id", "title": 1}} )
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "title" : "Java Primer", "ID" : ObjectId("5989b692b759cf05ab1c7195") }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "title" : "iOS Primer", "ID" : ObjectId("5989b692b759cf05ab1c7196") }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "title" : "Android Primer", "ID" : ObjectId("5989b692b759cf05ab1c7197") }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "title" : "Html5 Primer", "ID" : ObjectId("5989b692b759cf05ab1c7198") }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "title" : "Go Primer", "ID" : ObjectId("5989b692b759cf05ab1c7199") }
>

// 算数表达式:用于对一组数字 加减乘除取余
// $add: [exp1, exp2, ... expN]: 对数组中的多个元素进行相加, $fieldname: 用于来引用该字段的值
// 示例是对like字段的值 + like字段的值 + 字面量1 作为 "likes"字段的值
> db.articles.aggregate({"$project": {"likes": {"$add": ["$like", "$like", 1]}} })
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "likes" : 21 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "likes" : 61 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "likes" : 41 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "likes" : 81 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "likes" : 61 }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "likes" : 17 }

// $subtract: [exp1, exp2]: 数组中的第一个元素减去第二个元素
> db.articles.aggregate({"$project": {"likes": {"$subtract": ["$like", 2]}} })
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "likes" : 8 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "likes" : 28 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "likes" : 18 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "likes" : 38 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "likes" : 28 }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "likes" : 6 }

// $multiply:对数组中的多个元素相乘
db.articles.aggregate({"$project": {"likes": {"$multiply": ["$like", 2, 5]}} })
"_id" : ObjectId("5989b692b759cf05ab1c7195"), "likes" : 100 }
"_id" : ObjectId("5989b692b759cf05ab1c7196"), "likes" : 300 }
"_id" : ObjectId("5989b692b759cf05ab1c7197"), "likes" : 200 }
"_id" : ObjectId("5989b692b759cf05ab1c7198"), "likes" : 400 }
"_id" : ObjectId("5989b692b759cf05ab1c7199"), "likes" : 300 }
"_id" : ObjectId("5989b692b759cf05ab1c719a"), "likes" : 80 }

// $divide: 数组中的第一个元素除以第二个元素
db.articles.aggregate({"$project": {"likes": {"$divide": ["$like", 2]}} })
"_id" : ObjectId("5989b692b759cf05ab1c7195"), "likes" : 5 }
"_id" : ObjectId("5989b692b759cf05ab1c7196"), "likes" : 15 }
"_id" : ObjectId("5989b692b759cf05ab1c7197"), "likes" : 10 }
"_id" : ObjectId("5989b692b759cf05ab1c7198"), "likes" : 20 }
"_id" : ObjectId("5989b692b759cf05ab1c7199"), "likes" : 15 }
"_id" : ObjectId("5989b692b759cf05ab1c719a"), "likes" : 4 }

// $mod: 求数组中第一个元素除以第二个元素的余数
db.articles.aggregate({"$project": {"likes": {"$mod": ["$like", 3]}} })
"_id" : ObjectId("5989b692b759cf05ab1c7195"), "likes" : 1 }
"_id" : ObjectId("5989b692b759cf05ab1c7196"), "likes" : 0 }
"_id" : ObjectId("5989b692b759cf05ab1c7197"), "likes" : 2 }
"_id" : ObjectId("5989b692b759cf05ab1c7198"), "likes" : 1 }
"_id" : ObjectId("5989b692b759cf05ab1c7199"), "likes" : 0 }
"_id" : ObjectId("5989b692b759cf05ab1c719a"), "likes" : 2 }

// $substr: [exp, startOffset, numToReturn] : 字符串截取操作
> db.articles.aggregate({"$project": {"newValue": {"$substr": ["$title", 1, 2] } }})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "newValue" : "av" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "newValue" : "OS" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "newValue" : "nd" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "newValue" : "tm" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "newValue" : "o " }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "newValue" : "wi" }

// $concat:[exp1, exp2, ..., expN]: 字符串操作:将数组中的多个元素拼接在一起
> db.articles.aggregate({"$project": {"newValue": {"$concat": ["$title", "(", "$author", ")"]    } }})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "newValue" : "Java Primer(zhangsan)" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "newValue" : "iOS Primer(zhangsan)" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "newValue" : "Android Primer(zhangsan)" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "newValue" : "Html5 Primer(lisi)" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "newValue" : "Go Primer(lisi)" }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "newValue" : "Swift Primer(mengday)" }
>

// $toLower : exp, 字符串转小写
> db.articles.aggregate({"$project": {"newValue": {"$toLower": "$title"    } }})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "newValue" : "java primer" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "newValue" : "ios primer" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "newValue" : "android primer" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "newValue" : "html5 primer" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "newValue" : "go primer" }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "newValue" : "swift primer" }

// $toUpper: 字符串操作,转大写
> db.articles.aggregate({"$project": {"newValue": {"$toUpper": "$author"    } }})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "newValue" : "ZHANGSAN" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "newValue" : "ZHANGSAN" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "newValue" : "ZHANGSAN" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "newValue" : "LISI" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "newValue" : "LISI" }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "newValue" : "MENGDAY" }

// 为所有文档新增字段
> db.articles.update({}, {"$set": {"publishDate": new Date()}}, true, true)
WriteResult({ "nMatched" : 6, "nUpserted" : 0, "nModified" : 6 })

// 日期表达式:用于获取日期中的任意一部分,年月日时分秒 星期等
// $year、$month、$dayOfMonth、$dayOfWeek、$dayOfYear、$hour、$minute、$second
> db.articles.aggregate({"$project": {"month": {"$month": "$publishDate"}}})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "month" : 8 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "month" : 8 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "month" : 8 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "month" : 8 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "month" : 8 }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "month" : 8 }
>

> db.articles.aggregate({"$project": {"fasttime": {"$subtract": [{"$second": new Date()}, {"$second": "$publishDate"}]}}})

// $cmp: [exp1, exp2]: 用于比较两个字符串,exp1 == exp2 返回 0, 小于返回一个负数,大于返回一个正数
// $不能用于比较字符串
> db.articles.aggregate({"$project": {"result": {"$cmp": ["$like", 20]} }})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "result" : -1 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "result" : 1 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "result" : 0 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "result" : 1 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "result" : 1 }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "result" : -1 }

// $strcasecmp: 用于比较字符串,相等返回0
// $cmp 和 $strcasecmp 返回的结果是 0、-1、1
> db.articles.aggregate({"$project": {"result": {"$strcasecmp": ["$author", "mengday"]} }})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "result" : 1 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "result" : 1 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "result" : 1 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "result" : -1 }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "result" : -1 }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "result" : 0 }
>

// $eq: 用于判断两个表达式是否相等
// $ne: 不相等
// $gt: 大于
// $gte: 大于等于
// $lt: 小于
// $lte: 小于等于
> db.articles.aggregate({"$project": {"result": {"$eq": ["$author", "mengday"]}}})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "result" : true }

// $and:[exp1, exp2, ..., expN] 用于连接多个条件,当所有条件为真的时候为true
> db.articles.aggregate({"$project": {"result": {"$and": [{"$eq": ["$author", "mengday"]}, {"$gt": ["$like", 20]}]}}})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "result" : false }

// $or: [exp1, exp2, ..., expN]
> db.articles.aggregate({"$project": {"result": {"$or": [{"$eq": ["$author", "mengday"]}, {"$gt": ["$like", 20]}]}}})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "result" : true }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "result" : false }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "result" : true }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "result" : true }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "result" : true }
>

// $not: exp 用于取反操作
> db.articles.aggregate({"$project": {"result": {"$not": {"$eq": ["$author", "mengday"]}}}})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "result" : true }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "result" : true }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "result" : true }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "result" : true }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "result" : true }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "result" : false }

// $cond: [booleanExp, trueExp, falseExp]: 三位运算符
> db.articles.aggregate({"$project": {"result": {"$cond": [ {"$eq": ["$author", "mengday"]}, "111", "222" ]}}})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "result" : "222" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "result" : "222" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "result" : "222" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "result" : "222" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "result" : "222" }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "result" : "111" }

// $ifNull: [expr, replacementExpr]: 如果条件的值为null,则返回后面表达式的值,当字段不存在时字段的值也是null
> db.articles.aggregate({"$project": {"result": {"$ifNull": ["$notExistFiled", "not exist is null"]}}})
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "result" : "not exist is null" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7196"), "result" : "not exist is null" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7197"), "result" : "not exist is null" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7198"), "result" : "not exist is null" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7199"), "result" : "not exist is null" }
{ "_id" : ObjectId("5989b692b759cf05ab1c719a"), "result" : "not exist is null" }

$group: 分组

使用_id指定要分组的键,要分组的键也可以是多个,使用其他自定义的字段用于统计

// 过滤 + 分组
// _id:用于指定要分组的键,注意键的前面要使用$,意思是引用该字段的值
// 这里的count可以是任意自定义的键,后面用于描述应该怎么统计分组后的数据,这里是分组的每个文档加1,用于统计某个作者总共发表了多少篇文章
// 返回的结果: _id: 要分组的键,自定义字段:要统计的结果
> db.articles.aggregate( 
    {"$match": {"like": {"$gte" : 10} }}, 
    {"$group": {"_id": "$author", "count": {"$sum": 1}}} 
  )
{ "_id" : "lisi", "count" : 2 }
{ "_id" : "zhangsan", "count" : 3 }
>

// 对多个字段进行分组
> db.articles.aggregate( 
    {"$match": {"like": {"$gte" : 10} }}, 
    {"$group": {"_id": {"author": "$author", "like": "$like"}, "count": {"$sum": 1}}} 
  )

{ "_id" : { "author" : "zhangsan", "like" : 30 }, "count" : 1 }
{ "_id" : { "author" : "zhangsan", "like" : 20 }, "count" : 1 }
{ "_id" : { "author" : "lisi", "like" : 40 }, "count" : 1 }
{ "_id" : { "author" : "lisi", "like" : 30 }, "count" : 1 }
{ "_id" : { "author" : "zhangsan", "like" : 10 }, "count" : 1 }

// $sum: value, 对每个文档相加value,求和
// $avg: value, 求平均数
> db.articles.aggregate( {"$group": {"_id": "$author", "count": {"$avg": "$like"}}} )
{ "_id" : "mengday", "count" : 8 }
{ "_id" : "lisi", "count" : 35 }
{ "_id" : "zhangsan", "count" : 20 }
>

// $max: value, 求分组中某个字段最大的值
> db.articles.aggregate( {"$group": {"_id": "$author", "count": {"$max": "$like"}}} )
{ "_id" : "mengday", "count" : 8 }
{ "_id" : "lisi", "count" : 40 }
{ "_id" : "zhangsan", "count" : 30 }
>

// $min: value, 求分组中某个字段最小的值
> db.articles.aggregate( {"$group": {"_id": "$author", "count": {"$min": "$like"}}} )
{ "_id" : "mengday", "count" : 8 }
{ "_id" : "lisi", "count" : 30 }
{ "_id" : "zhangsan", "count" : 10 }
>

// $first: value, 求分组中第一个值
> db.articles.aggregate( {"$group": {"_id": "$author", "count": {"$first": "$like"}}} )
{ "_id" : "mengday", "count" : 8 }
{ "_id" : "lisi", "count" : 40 }
{ "_id" : "zhangsan", "count" : 10 }

// $last: value, 求分组中第一个值
> db.articles.aggregate( {"$group": {"_id": "$author", "count": {"$last": "$like"}}} )
{ "_id" : "mengday", "count" : 8 }
{ "_id" : "lisi", "count" : 30 }
{ "_id" : "zhangsan", "count" : 20 }

// $addToSet: exp, 将分组后的每个文档指定的值放在set集合中,集合不重复,无序
> db.articles.aggregate( {"$group": {"_id": "$author", "like": {"$addToSet": "$like"}}} )
{ "_id" : "mengday", "like" : [ 8 ] }
{ "_id" : "lisi", "like" : [ 30, 40 ] }
{ "_id" : "zhangsan", "like" : [ 30, 20, 10 ] }

// $push: exp, 将分组后的每个文档指定的值放在数组中,允许重复,有序
> db.articles.aggregate( {"$group": {"_id": "$author", "like": {"$push": "$like"}}} )
{ "_id" : "mengday", "like" : [ 8 ] }
{ "_id" : "lisi", "like" : [ 30, 40 ] }
{ "_id" : "zhangsan", "like" : [ 30, 20, 10 ] }

> db.articles.findOne()
{
        "_id" : ObjectId("5989b692b759cf05ab1c7195"),
        "author" : "zhangsan",
        "title" : "Java Primer",
        "like" : 10,
        "publishDate" : ISODate("2017-08-09T00:50:36.198Z"),
        "comments" : [
                "good",
                "very good"
        ]
}

// $unwind: 将数组中的每个值拆分成一个单独的文档
> db.articles.aggregate( {"$unwind": "$comments"} )
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "author" : "zhangsan", "title" : "Java Primer", "like" : 10, "publishDate" : ISODate("2017-08-09T00:50 :36.198Z"), "comments" : "good" }
{ "_id" : ObjectId("5989b692b759cf05ab1c7195"), "author" : "zhangsan", "title" : "Java Primer", "like" : 10, "publishDate" : ISODate("2017-08-09T00:50 :36.198Z"), "comments" : "very good" }
>

$sort: 用于对上一次处理的结果进行排序,1:升续 -1:降续

> db.articles.aggregate( 
    {"$match": {"like": {"$gte" : 10} }}, 
    {"$group": {"_id": "$author", "count": {"$sum": 1}}},
    {"$sort": {"count": -1}} 
  )

{ "_id" : "zhangsan", "count" : 3 }
{ "_id" : "lisi", "count" : 2 }

$limit: 用于条数限制

> db.articles.aggregate( 
    {"$match": {"like": {"$gte" : 10} }}, 
    {"$group": {"_id": "$author", "count": {"$sum": 1}}},
    {"$sort": {"count": -1}},
    {"$limit": 1} 
)

{ "_id" : "zhangsan", "count" : 3 }

$skip: 跳过前N条文档,和limit结合可用于分页

db.articles.aggregate( 
    {"$match": {"like": {"$gte" : 10} }}, 
    {"$group": {"_id": "$author", "count": {"$sum": 1}}},
    {"$sort": {"count": -1}},
    {"$skip": 1},
    {"$limit": 1} 
)

// 以上聚合首先通过$match: 过滤掉不匹配的文档,接着讲满足条件的文档交给$group进行分组,分组后将将分组后的结果交给$sort进行排序,然后将排序后的结果交给$skip处理,跳过前1条,把剩下的文档交给$limit处理,获取最终的聚合结果。

聚合框架,就是将上一个操作符处理的结果交个下一个操作符继续处理(这就是Linux中的管道操作),可以使用任意多个操作符,同一个操作符也可以使用多次

聚合命名

count(): 求数量

> db.articles.count()
6
> db.articles.count({"author": "zhangsan"})
3

distinct(“filedname”)

求某个字段不同的值

> db.articles.distinct("author")
[ "zhangsan", "lisi", "mengday" ]

group()

// key: 用于指定要分组的键
// initial: 对于分组统计的字段设置键名和初始值
// reduce: 循环每个分组中的每个文档,一组循环完了会继续下一组,

> db.articles.group({
  "key": "author",
  "initial": {"sum": 0},
  "reduce": function(doc, prev) {
  if(doc.like > 10) {
    prev.sum += 1;
  }}
})
[ { "sum" : 4 } ]

// key: {"fieldname": true} 和 key: "filedname" 有很大的区别:
// key: {"fieldname": true} 分组的结果会带有每个分组的字段,reduce每循环一组就会重新执行以下初始化initial
// key: "filedname", 结果中不带分组的字段,而且好像当执行下一个分组的时候不会进行初始化,下一组的统计结果是在上一组的基础上完成的,所有组循环完了只得到最后的结果,这种方式感觉不像是平常见到的分组
> db.articles.group({
    "key": {"author": true}, 
    "initial": {"sum": 0}, 
    "reduce": function(doc, prev) {
        if(doc.like > 10) {
            prev.sum += 1;
        }
    }
})

[
        {
                "author" : "zhangsan",
                "sum" : 2
        },
        {
                "author" : "lisi",
                "sum" : 2
        },
        {
                "author" : "mengday",
                "sum" : 0
        }
]

// condition: 用于分组前筛选掉不满足条件的文档
> db.articles.group({
    "key": {"author": true}, 
    "initial": {"sum": 0}, 
    "reduce": function(doc, prev) {
        if(doc.like > 10) {
            prev.sum += 1;
        }
    }, 
    "condition":{"author": {"$ne": "mengday"}}
})

[
        {
                "author" : "zhangsan",
                "sum" : 2
        },
        {
                "author" : "lisi",
                "sum" : 2
        }
]

// finalize: 用于对分组后的结果进一步处理,每组都会调用finalize
> db.articles.group({
    "key": {"author": true}, 
    "initial": {"sum": 0}, 
    "reduce": function(doc, prev) {
        if(doc.like > 10) {
            prev.sum += 1;
        }
    }, 
    "condition":{"author": {"$ne": "mengday"}},
    "finalize": function(doc){
        if(doc.author == "zhangsan"){
            delete doc
        }
    }
})

[
        {
                "author" : "zhangsan",
                "sum" : 3
        },
        {
                "author" : "lisi",
                "sum" : 2
        }
]

使用聚合框架aggregate({“$group: {}”}) 和 group()都可以进行分组,但group好像没有聚合框架这么灵活,如group()不能投射,分组后的结果不知道怎么过滤掉一些不满足条件的值,怎么对分组后的结果排序,分页等,这些都可以在聚合框架中使用管道操作很轻易的实现,group()适用于简单的分组,聚合框架适用于更复杂的分组处理(注意:聚合框架分组只是其中的一个管道,也就是说分组只是聚合框架的其中一个功能而不是说聚合框架就是用来分组的)

MapReduce

mapReduce强大、灵活,使用Javascript作为查询语言能够表达任意复杂的逻辑,但是也非常慢,不应该用于实施数据分析。能够在多台服务器上并行执行,当所有机器都完成是,再讲这些结果合并起来再统一聚合一下

http://www.cnblogs.com/Joe-T/p/4264910.html

相关文章