【知识小课堂】 之 聚合函数
来源:互联网 发布:js 大于等于 小于等于 编辑:程序博客网 时间:2024/04/30 11:18
我们先来看几个简单的聚合命令:
1.count
> db.foo.count()4> db.foo.find({_id:{$gte:2}}){ "_id" : 2, "x" : 2 }{ "_id" : 3, "x" : 3 }> db.foo.find({_id:{$gte:2}}).count()2> db.foo.count({_id:{$gte:2}})2>
这个命令很简单,但我们往往会忽略 最后一种用法,其实count() 函数里面也可以加条件的。
类似于sql 的: select count(*) from table_name;
2.distinct
> db.order_detail.find(){ "_id" : 1, "cust_id" : 1, "order_id" : 1, "prod_id" : 1 }{ "_id" : 2, "cust_id" : 1, "order_id" : 1, "prod_id" : 2 }{ "_id" : 3, "cust_id" : 2, "order_id" : 2, "prod_id" : 2 }{ "_id" : 4, "cust_id" : 3, "order_id" : 2, "prod_id" : 1 }{ "_id" : 5, "cust_id" : 3, "order_id" : 3, "prod_id" : 3 }
示例数据如上。如果我们要查询 有多少种prod_id
db.runCommand({distinct:"order_detail",key:"prod_id"}){"values" : [1,2,3],"stats" : {"n" : 5,"nscanned" : 5,"nscannedObjects" : 5,"timems" : 0,"cursor" : "BasicCursor"},"ok" : 1}
功能类似于sql : select distinct prod_id from table_name
3.GROUP
我们再来先看示例:
> db.runCommand({group:{ "ns":"order_detail", ... key:{cust_id:true}, ... initial:{"qty":0},... "$reduce":function(doc,prev){... prev.qty +=1; } ... } } ){"retval" : [{"cust_id" : 1,"qty" : 2},{"cust_id" : 2,"qty" : 1},{"cust_id" : 3,"qty" : 2}],"count" : 5,"keys" : 3,"ok" : 1}
关键词说明:
ns: 要分组的集合
Key :分组依据的键
Initial:初始化
Reduce: reduce 函数
sort: 排序依据;
使用GROUP 可以求:
Count 计数;
SUM 和
AVG 平均值
MAX 最大值
MIN 最小值
FIRST 第一个值
LAST 最后一个值
如果指定了排序键值,那么使用 $first / $last 性能会比 MAX/ MIN 好。但在使用$FIRST/$ LAST 时,$sort 放在 $FIRST/$ LAST 前面
以下是一个书上的例子:
按日期分组,列出每天最后交易时间及价格
> db.runCommand({"group" : {... "ns" : "stocks",... "key" : "day",... "initial" : {"time" : 0},... "$reduce" : function(doc, prev) {... if (doc.time > prev.time) {... prev.price = doc.price;... prev.time = doc.time;... }... }}})
db.scores.aggregate(... {... "$sort" : {"score" : 1}... },... {... "$group" : {... "_id" : "$grade", ... "lowestScore" : {"$first" : "$score"}, ... "highestScore" : {"$last" : "$score"}... }... })
当然,在group 中,你也可以使用 $LIMIT,$SKIP ,同时也可以添加条件进行汇总查询。
$condition 添加查询条件
> db.order_detail.find(){ "_id" : 1, "cust_id" : 1, "order_dt" : ISODate("2014-04-30T16:00:00Z"), "order_id" : 1, "prod_id" : 1 }{ "_id" : 2, "cust_id" : 1, "order_dt" : ISODate("2014-08-11T05:45:50.584Z"), "order_id" : 1, "prod_id" : 2 }{ "_id" : 3, "cust_id" : 2, "order_dt" : ISODate("2014-08-11T05:45:50.584Z"), "order_id" : 2, "prod_id" : 2 }{ "_id" : 4, "cust_id" : 3, "order_dt" : ISODate("2014-08-11T05:45:50.584Z"), "order_id" : 2, "prod_id" : 1 }{ "_id" : 5, "cust_id" : 3, "order_dt" : ISODate("2014-08-11T05:45:50.584Z"), "order_id" : 3, "prod_id" : 3 } > db.runCommand({group:{ "ns":"order_detail", ... key:{cust_id:true}, ... initial:{"qty":0},... "$reduce":function(doc,prev){... prev.qty +=1; } ,... condition:{order_dt:{$gt:new Date('2014,08,01')}}... } } ){"retval" : [{"cust_id" : 1,"qty" : 1},{"cust_id" : 2,"qty" : 1},{"cust_id" : 3,"qty" : 2}],"count" : 4,"keys" : 3,"ok" : 1}>
Condition 也可以简写成 cond, 或:query,q
4.Aggregate()
还是先看示例:
> db.order_detail.aggregate( {$group:{_id:"$cust_id",count:{$sum:1}}} ){"result" : [{"_id" : 3,"count" : 2},{"_id" : 2,"count" : 1},{"_id" : 1,"count" : 2}],"ok" : 1}>
aggregate() 聚合函数功能就强大了:
关键词如下:
{$project:{“author”:1}} 指定要显示的字段名称
{$match:{“state”:”OR”}} 指定查询的条件
{$group:{_id:”$day”}} 指定分组的字段
{$sort:{count:-1}} 指定排序
{$limit:5} 指定返回的数量 ,当然也可以使用$skip
{unwind:”$comments”} 指定拆分的字段 (独立使用)
4.1 这里主要来讲讲 $project :
在sql 中,我们有 substr(col1,1,10), to_str(create_dt,'yyyy') ,此类的功能,只取字段的某一部分。在MONGODB 中,我们也可以实现。
这就是我们这里要讲的。
a. 指定某些字段要显示: {$project:{"userId":"$_id","_id":0}}
b.字符串处理:
"$substr":{$substr:[col1,1,10]} ,类似于 substring(col1,1,10)
“$concat”:{"$concat":[col1,col2]}, 类似于 col1+col2
"$toLower":{"$toLower:col1"} ,类似于 lower(col1)
"$toUpper":{"$toLower:col1"}
b.日期处理:
"$year","$month”,"$week","$dayOfMonth","$dayOfweek","$dayOfYear","$hour","$minuse","$second" ,使用这些函数,可以返回你所需要的一个日期字段的部分值。
c.数字计算:
“$add” + ,"subtract" - ,'$multiply' *,'$divide' /,"$mod" 取余。这些计算操作符,可以把多个字段的计算后返回。
d.逻辑表达式:
还可以进行逻辑处理,返回一个新的字段值:
“$cmp”: [expr1,expr2]
expr1=expr2: 0;
expr1<expr2: 负数;
expr1>expr2: 正数;
“$strcasecmp”:[str1,str2]
区分str1,str2 大小
"$and":[expr1,expr2]
所有条件为true,返回 true,否则false;
"$or":[expr1,expr2]
只要有一条件为true,返回 true,否则false;
"$not":expr1
取反
"$cond":[booleanExpr: trueExpr,falseExpr]
如果 booleanExpr=true,返回trueExpr ,否则返回 falseExpr
"$ifNull":[expr,replacementExpr] 类似于: oracle: nvl()
4.2 多重分组
先看一个官方的示例:
db.zipcodes.aggregate( [ { $group : { _id : { state : "$state", city : "$city" }, pop : { $sum : "$pop" } } }, { $group : { _id : "$_id.state", avgCityPop : { $avg : "$pop" } } }] )
在aggregate 中,可以使用多重组合。也就是使用前一个分组后的数据,再进行一次分组。
比如下面的sql:
select ip.city,count(distince user_cookie) from website_open_log
group by ip.city
我要统计网站的登录用户的分布。但汇总的数据为有多人人,而不是有多少次。同一个用户可能有多次访问。
下面的代码中,我使用了两种方法,统计结果稍有些不同,但在这里很能说明问题
db.website_open_log.aggregate( {$match:{company_id:1}}, {$group:{_id:"$cookie", ip:{$first:"$ip.province"} } }, {$group:{_id:"$ip", qty:{$sum:1} } }, {$sort:{qty:-1}}, {$limit:10} )
> db.website_open_log.aggregate({$match:{company_id:1}},... {$group:{_id:{"cookie":"$cookie","province":"$ip.province"},... qty:{$sum:1}... }... },... {$group:{_id:"$_id.province",... qty1:{$sum:1}... }... },... {$sort:{qty1:-1}}... );
- 【知识小课堂】 之 聚合函数
- 【知识小课堂】 mongodb 之 objectId
- 【知识小课堂】4 之 索引
- 【知识小课堂】mongodb 之 查询关键词使用
- 【知识小课堂】mongodb 之 特殊集合及索引
- java 课堂小知识总结
- java 课堂小知识总结
- C语言知识学习课堂小笔记
- 【知识小课堂】 mongodb 之字段中的【 数组】、【内嵌文档】
- Go语言小知识之append()函数
- 数据库 之 聚合函数
- Mysql之聚合函数
- 查询语句之聚合函数
- sql语句之聚合函数
- MySQL之聚合函数查询
- MySQL知识(七)——聚合函数、加密函数
- 知识课堂与生命课堂
- oracle之聚合函数(分组函数)详解
- 编译库文件资料
- 趴心氖颗潘
- 小希的迷宫
- Spring MVC入门
- 【树状数组 + 容斥原理】 HDOJ 4947 GCD Array
- 【知识小课堂】 之 聚合函数
- 俸菊疵韶训
- poj 1674 Sorting by Swapping
- max = (a>b) ? (c>d ? 1 : 2) : 3
- 多线程
- nyist oj 214 单调递增子序列(二) (动态规划经典)
- android的ListView点击item使item展开的做法
- Codeforces #261 (Div. 2) A. Pashmak and Garden(水题)
- Cocos2d-x 3.x 系列教程02-创建自定义项目