mongo14

Wesley13
• 阅读 705
group,aggregate,mapReduce

分组统计: group()
简单聚合: aggregate()
强大统计: mapReduce()


db.collection.group(document)
document:{
            key:{key1:1,key2:1},  //根据那几个字段分组
            cond:{},  //筛选的条件
            reduce: function(curr,result) {  //分组之后的聚合运算,curr是一行数据,result是计算后的结果
            },
            initial:{},  //初始化result里面
            finalize:function() {  //reduce一组都执行完毕后最后执行的函数
            }
          }
          
#计算每个栏目下(cat_id)的商品数 count()操作
select  cat_id,count(*) from goods group by cat_id;  //mysql操作

use shop
db.goods.group(
{
    key:{cat_id:1},   //根据哪个字段分组
    cond:{},          //所有行取出来,不加条件
    reduce:function(curr,result) {//reduce的执行过程:每一行就是一个curr,每一组共用一个result变量,
        result.cnt += 1;       //result.cnt是每组有多少行,每个组有一个result,
    },
    initial:{cnt:0}
    }
):
[
    {
        "cat_id" : 4.0,
        "cnt" : 3.0
    },
    {
        "cat_id" : 8.0,
        "cnt" : 3.0
    },
    {
        "cat_id" : null,
        "cnt" : 2.0
    }
]




#查询每个栏目下价格高于3500元的商品数量
use shop
db.goods.group(
{
    key:{cat_id:1},   //cat_id分组,并且查出car_id和shop_price字段
    cond:{shop_price:{$gt:3500}},
    reduce:function(curr,result) {
        result.cnt += 1;
    },
    initial:{cnt:0}
}
):
[
    {
        "cat_id" : 3.0,
        "shop_price" : 5999.0,
        "cnt" : 1.0
    },
    {
        "cat_id" : 5.0,
        "shop_price" : 3700.0,
        "cnt" : 1.0
    }
]




#查询每个栏目下价格大于3000元的商品个数
{
    key:{cat_id:1},
    cond:{},
    reduce: function(curr,result) {
        result.total += 1;
    },
    initial:{total:0}
}:
[
    {
        "cat_id" : 4.0,
        "total" : 3.0
    },
    {
        "cat_id" : 8.0,
        "total" : 3.0
    },    
    {
        "cat_id" : null,
        "total" : 2.0
    }
]



#计算每个栏目下的商品库存量 sum()操作
select  sum(goods_number) from goods group by cat_id;

use shop
db.goods.group(
{
    key:{cat_id:1},
    cond:{},
    reduce: function(curr,result) {
            result.total += curr.goods_number;
    },
    initial:{total:0}
}
):
[
    {
        "cat_id" : 4.0,
        "total" : 3.0
    },
    {
        "cat_id" : 8.0,
        "total" : 61.0
    },
    {
        "cat_id" : null,
        "total" : NaN
    }
]



#查询每个栏目最贵的商品价格, max()操作
select  max(shop_price) from goods group by cat_id;

use shop
db.goods.group(
{
    key:{cat_id:1},
    cond:{},
    reduce:function(curr , result) {
        if(curr.shop_price > result.max) {
            result.max = curr.shop_price;
        }
    },
    initial:{max:0}
}
):



#查询每个栏目下商品的平均价格
select cat_id,avg(shop_price) from goods group by cat_id;

use shop
db.goods.group(
{
    key:{cat_id:1},          //相当于group by 
    cond:{},                       //相当于where
    reduce:function(curr , result) {             //相当于sum.avg函数
        result.cnt += 1;
        result.sum += curr.shop_price;
    },
    initial:{sum:0,cnt:0},                //进这个组执行一下
    finalize:function(result) {      //出这个组执行一下,   组操作完毕后的回调函数
        result.avg = result.sum/result.cnt;
    }
}
):
[
    {
        "cat_id" : 4.0,
        "sum" : 6891.0,
        "cnt" : 3.0,
        "avg" : 2297.0
    },
    {
        "cat_id" : 8.0,
        "sum" : 226.0,
        "cnt" : 3.0,
        "avg" : 75.3333333333333
    },
    {
        "cat_id" : null,
        "sum" : NaN,
        "cnt" : 2.0,
        "avg" : NaN
    }
]





注意: 
1:group需要我们手写聚合函数的业务逻辑
2:group 不支持集群shard cluster, 无法分布式运算

3:分布式可以用 aggregate() (version2.2) , 
或者mapReduce() (version2.4)

GROUP BY        $group
HAVING            $match
SELECT            $project
ORDER BY        $sort
LIMIT            $limit
SUM()            $sum
COUNT()            $sum


#查询每个栏目下的商品数量
select count(*) from goods group by cat_id;

db.goods.aggregate(
[
    {
        $group:{
            _id:"$cat_id",     //根据cad_id分组
            total:{$sum:1}     //乘以1
        }
    }     
]
):
{
    "_id" : null,
    "total" : -2.0
}
{
    "_id" : 14.0,
    "total" : -2.0
}
{
    "_id" : 2.0,
    "total" : -1.0
}
{
    "_id" : 13.0,
    "total" : -2.0
}



#查询goods下有多少条商品,select count(*) from goods
[
{$group:{_id:null,total:{$sum:1}}}
];
{
    "_id" : null,
    "total" : 33.0
}



#查询每个栏目下 价格大于3000元的商品个数
use shop
db.goods.aggregate(
[
    {$match:{shop_price:{$gt:3000}}},
    {$group:{_id:"$cat_id",total:{$sum:1}}}
]
):
{
    "_id" : 5.0,
    "total" : 1.0
}
{
    "_id" : 3.0,
    "total" : 2.0
}




#查询每个栏目下 价格大于50元的商品个数
#并筛选出"满足条件的商品个数" 大于等于3的栏目 
select cat_id,count(*) as cnt from goods where shop_price>3000 group by cat_id having cnt>=2


use shop
db.goods.aggregate(
[
    {$match:{shop_price:{$gt:3000}}},    //放在group之前是where
    {$group:{_id:"$cat_id",total:{$sum:1}}},
    {$match:{total:{$gte:2}}}             //放在group之后是having
]
):
{
    "_id" : 3.0,
    "total" : 2.0
}





#查询每个栏目下的库存量
use shop
db.goods.aggregate(
[
    {$group:{_id:"$cat_id" , total:{$sum:"$goods_number"}}},   //cat_id分组,goods_number求和,
]
):
{
    "_id" : 5.0,
    "total" : 8.0
}
{
    "_id" : 15.0,
    "total" : 2.0
}




#查询每个栏目下的库存量,并按库存量排序
use shop
db.goods.aggregate(
[
{$group:{_id:"$cat_id" , total:{$sum:"$goods_number"}}},
{$sort:{total:1}}         //1是升序
]
)



#查询每个栏目下的库存量,并按库存量排序
use shop
db.goods.aggregate(
[
    {$group:{_id:"$cat_id" , total:{$sum:"$goods_number"}}},
    {$sort:{total:1}},
    {$limit:3}       //取前3个
]
):
{
    "_id" : null,
    "total" : 0
}
{
    "_id" : 2.0,
    "total" : 0.0
}
{
    "_id" : 15.0,
    "total" : 2.0
}



#查询每个栏目的商品平均价格,并按平均价格由高到低排序
select cat_id ,avg(shop_price) as pj from goods group by cat_id order by pj desc limit 3

use shop
db.goods.aggregate(
[
    {$group:{_id:"$cat_id" , avg:{$avg:"$shop_price"}}},     //car_id排序,shop_price求平均,
    {$sort:{avg:-1}},
    {$limit:3}       
]
):
{
    "_id" : 5.0,
    "avg" : 3700.0
}
{
    "_id" : 4.0,
    "avg" : 2297.0
}
{
    "_id" : 3.0,
    "avg" : 1746.06666666667
}

mapReduce 随着"大数据"概念而流行,mapReduce的真正强项在于分布式。
其实mapReduce的概念非常简单,比aggregate要简单,从功能上说,相当于RDBMS(传统数据库)的 group 操作。

当数据非常大时,像google,有N多数据中心,数据都不在地球的一端,用group力所不及.group既然不支持分布式, 由于单台服务器的运算能力必然是有限的.

而mapRecuce支持分布式(不是算法好),而是支持大量的服务器同时工作,用蛮力来统计.mapRecuce就是group和aggregate,只不过支持分布式。

mapRecuce的工作过程:1.map-->映射,2.reduce->归约

map: 1.先在全世界机器找(分布式集群上找),把属于同一个组的数据,映射到一个数组上.cat_id [23,2,6,7],2.reduce: 把数组(同一组)的数据,进行运算.





#用mapReduce计算每个栏目的库存总量

//map函数(进行映射工作,映射成一个二维数组)
var map = function() {
    emit(this.cat_id,this.goods_number);  //根据cat_id分组,
}

/*
{
    cat_id1:[goods_number1,goods_number2,goods_number3.....],
    cat_id2:[goods_number1,goods_number2,goods_number3.....]
    cat_id3:[goods_number1,goods_number2,goods_number3.....]
}
*/

var reduce = function(cat_id,numbers) {   //对数组做处理,求goods_number的和,
    return Array.sum(numbers);    //mongo对js的数组增加的求和方法
}

/*
{
    _id:cat_id1, value:goods_number1+goods_number2+goods_number3.....,
    _id:cat_id1, value:goods_number1+goods_number2+goods_number3.....,
    _id:cat_id1, value:goods_number1+goods_number2+goods_number3.....,
}
*/

db.goods.mapReduce(map,reduce,{out:'res'});    //out计算的结果放在res集合里面去,
//多了一个res表
show tables
db.res.find():
{
    "_id" : null,
    "value" : NaN
}
{
    "_id" : 2.0,
    "value" : 0.0
}
{
    "_id" : 3.0,
    "value" : 203.0
}
{
    "_id" : 4.0,
    "value" : 3.0
}
{
    "_id" : 15.0,
    "value" : 2.0
}

//查看array的所有方法:
for (var k in Array){
        print(k)
}:
contains
unique
shuffle
tojson
fetchRefs
sum
avg
stdDev




#用mapReduce计算每个栏目下商品的平均价格
var map = function() {
    emit(this.cat_id,this.shop_price);
}
var reduce = function(cat_id,values) {
    return Array.avg(values);
}
db.goods.mapReduce(map,reduce,{out:'res'});
:
{
    "_id" : null,
    "value" : NaN
}
{
    "_id" : 2.0,
    "value" : 823.33
}
{
    "_id" : 3.0,
    "value" : 1746.06666666667
}

var map = function() {
    if(this.jing < 0 || this.wei < 0){
        return;
    }
    var j = Math.floor(this.jing/5)*5;
    var w = Math.floor(this.wei/5)*5;
    var block = j+":"+w;
    emit(block,1);
}
var reduce = function(block,values) {
    return Array.sum(values);
}
db.goods.mapReduce(map,reduce,{out:'res'});
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这