MongoDB聚合

MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果

每个文档通过一个由多个阶段(stage)组成的管道(可以对每个阶段的管道进行分组、过滤等功能),然后经过一系列的处理输出相应的结果

MongoDB中聚合方法使用aggregate()方法,语法格式如下:
    db.集合名称.aggregate({管道:{表达式}})

MongoDB常用表达式:

表达式:用来处理输入文档并输出
语法:表达式:'$字段名'   ----> avg_age: {$avg: "$age"}

请输入图片描述

请输入图片描述

管道

管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的输入,MongoDB聚合管道将MongoDB文档在一个管道处理完毕后的结果传递给下一个管道进行处理

表达式:处理输入文档并输出,表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档

聚合管道中常用的操作:
    $group:将集合中的文档分组,可用于统计结果
    $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档
    $match:用于过滤数据,只输出符合条件的文档($match使用MongoDB的标准查询操作)
    $sort:将输入文档排序后输出
    $limit:用来限制MongoDB聚合管道返回的文档数
    $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档
    $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值
    $geoNear:输出接近某一地理位置的有序文档
    

1. $group:将集合中的文档按照某个字段分组(group后面有几个字段结果就有几个字段)
    db.col.aggregate({$group: {_id:'$xxx', count: {$sum:1}}})
    _id用来表示分组使用的字段,格式为$字段名
    
    > db.test1.aggregate({$group:{_id:"$gender", count:{$sum:1}, avg_age:{$avg:"$age"}}})
    { "_id" : false, "count" : 2, "avg_age" : 18 }
    { "_id" : true, "count" : 5, "avg_age" : 27.8 }
    
    将所有文档分为一组:group by null
        db.col.aggregate({$group: {_id:null, count: {$sum:1}}})
    
    按照多个字段分组:
        db.col.aggregate(
            {$group:{_id:{字段名:"$字段名", 字段名:"$字段名",.....}}}
        )
    
    如果一个键对应的值为字典类型,取值时可使用$字段名.键取其内部的值


2. $project:修改输入文档的结构,如重命名(as)、增加、删除字段、创建计算结果等(投影操作)
    > db.test1.aggregate({$group:{_id:"$gender", count:{$sum:1}, avg_age:{$avg:"$age"}}})
    { "_id" : false, "count" : 2, "avg_age" : 18 }
    { "_id" : true, "count" : 5, "avg_age" : 27.8 }
    > db.test1.aggregate(
    ... {$group:{_id:"$gender", counter:{$sum:1}, avg_age:{$avg:"$age"}}},   # 分组
    ... {$project:{gender:"$_id", count:"$counter", avg_age:"$avg_age", _id:0}}  # 文档处理(投影处理)
    ... )
    { "gender" : false, "count" : 2, "avg_age" : 18 }
    { "gender" : true, "count" : 5, "avg_age" : 27.8 }
    
3. $match:用于过滤文档数据,输出符合条件的文档(使用标准查询操作)
    - match是管道命令可将结果交给下一个管道,find不可以
    > db.test1.aggregate(
    ... {$match:{age:{$gt:18}}},
    ... {$group:{_id:"$gender", counter:{$sum:1}, avg_age:{$avg:"$age"}}}
    ... )
    { "_id" : true, "counter" : 3, "avg_age" : 35 }
    
4. $sort:将输入文档排序后输出
    > db.test1.aggregate(
    ... {$group:{_id:"$gender", counter:{$sum:1}}},
    ... {$sort:{counter:-1}}
    ... )
    { "_id" : true, "counter" : 5 }
    { "_id" : false, "counter" : 2 }

5. $limit和$skip
    - $limit:限制聚合管道返回的文档数
    - $skip:跳过指定数量的文档,并返回余下的文档(先写skip,再写limit)
    > db.test1.aggregate({$limit:2})
    { "_id" : ObjectId("5e341734f059c66621de99fb"), "name" : "郭靖", "hometown" : "蒙古", "age" : 20, "gender" : true }
    { "_id" : ObjectId("5e34175df059c66621de99fc"), "name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false }
    
    > db.test1.aggregate(
    ... {$group:{_id:"$gender", counter:{$sum:1}}},
    ... {$sort:{counter:-1}},
    ... {$skip:1},
    ... {$limit:1}
    ... )
    { "_id" : false, "counter" : 2 }
    
    
6. $unwind:将文档中的某个数组类型字段拆分为多条,每条包含数组的一个值(展开)

    ```> db.info.insert({name:"朱翔", favorite:["王者荣耀", "刺激战场", "打麻将"]})
    WriteResult({ "nInserted" : 1 })
    > db.info.aggregate(
    ... {$unwind:"$favorite"}
    ... )
    { "_id" : ObjectId("5e34e40088cc04cff3d3bf4a"), "name" : "朱翔", "favorite" : "王者荣耀" }
    { "_id" : ObjectId("5e34e40088cc04cff3d3bf4a"), "name" : "朱翔", "favorite" : "刺激战场" }
    { "_id" : ObjectId("5e34e40088cc04cff3d3bf4a"), "name" : "朱翔", "favorite" : "打麻将" }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值