mongodb 分组聚合_MongoDB干货总结
什么是MongoDB
基于分布式文件存储的数据库,介于非关系型和关系型数据库之间。
MongoDB和MySQL对比
MongoDB有什么特点
(1)面向集合存储数据,数据以json格式存储;
(2)查询功能强大,几乎可以实现所有关系型数据库的单表查询功能;
(3)自带分布式文件系统,方便集群部署;
(4)自带了对map-reduce运算框架的支持。
MongoDB为什么快
(1)没有事务约束;
(2)使用的内存映射技术 ,写入数据时候只要在内存里完成就可以返回给应用程序,写入磁盘是异步操作;热点数据放入内存;数据在磁盘中相对集中,减少随机读写耗费的磁头定位时间;
(3)没有join,不使用关系。没有关系的存在,就表示每个数据都好比是拥有一个单独的存储空间,然后一个聚集索引来指向。
MongoDB适用场景
(1)网站实时数据处理,如PV、UV、统计商品的收藏次数、加入购物车次数、曝光次数等。
(2)服务器日志记录;
(3)大数据量,TB甚至PB级别的数据存储;
(4)数据模型经常变化,需要支持水平扩展
(5)游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
视频直播,使用 MongoDB 存储用户信息、礼物信息等。
MongoDB不适用场景
(1)数据修改需要严格的事物控制;
(2)功能的业务关系复杂、涉及到多表关联;
(3)比较重要的业务数据,如订单、商品、用户等数据。
MongoDB集合
MongoDB的集合,可类比于MySQL的表,字段(field)可类比于MySQL的列(column)。区别是,集合的filed是可动态扩展的,并且数据类型没有限制,不像Mysql需要先定义列名、列的字段类型等。
此外,集合无需像mysql的表一样事先定义。使用db.collectionName.insert()语句,插入一条json数据,该集合便生成了。
集合由文档组成,每个文档就是一条json数据。
插入文档
向集合中插入一个文档(类比向表中插入一条数据):
`db.getCollection("b2b_theme_activity").insert( { "merchant_code": "1ed0528595197975fa72f5ec8f9e0c62", "dfx_type": NumberInt("1"), "create_time": ISODate("2020-03-16T22:36:01.964Z"), "member_code": "e69e61a77b1ccc7b90be7995c6a6021f", "user_name": "李郃", "merchant_name": "南京好享家智能家居有限公司", source: NumberInt("10"), "visit_duration": "", type: NumberInt("11"), "member_name": "测试企业开户01", "theme_activity_page_title": "测试test01", "login_name": "17366180925", "user_id": "1161150535707852801", event: NumberInt("20"), "theme_activity_id": "1238383672212533250"} ); 复制代码
修改文档
语法
修改文档的语法是:
db.collection.update( , , { upsert: , multi: , writeConcern: })复制代码
- query : update的查询条件,类似sql update查询内where后面的。
- update : update的对象和一些更新的操作符(如,,,inc...)等,也可以理解为sql update查询内set后面的
- upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
- writeConcern :可选,抛出异常的级别。
例子
现有集合:t_test_log,希望修改requestUri为:/ops/api/b2b/theme-activities的文档的requestSource值为1,且只修改符合条件的第一条数据,脚本如下:
db.t_test_log.update({'requestUri':'/ops/api/b2b/theme-activities'},{$set:{'requestSource': '1'}})复制代码
如果想把所有符合条件的文档数据都修改了,则加上:{multi:true}
db.t_test_log.update({'requestUri':'/ops/api/b2b/theme-activities'},{$set:{'requestSource': '2'}}, {multi:true})复制代码
删除文档
语法
db.collection.remove( , )复制代码
- query:查询
- justOne:是否只删除符合条件的第一个文档,true:是,false:否 默认false
例子
删除符合条件的第一个文档:
db.t_test_log.remove({'requestUri':'/ops/api/b2b/theme-activities/11111/22222/testPut'},1)复制代码
删除符合条件的所有文档:
db.t_test_log.remove({'requestUri':'/ops/api/b2b/theme-activities/11111/22222/testPut'})复制代码
查询
简单查询
select * from spu where spu_name="test0123"db.spu.find({ spu_name:"test0123" })复制代码
and
select * from spu where spu_name="test0123" and type=3db.spu.find({spu_name:"test0123", type:"3" });复制代码
like
select * from user where username like "%test0123%"db.user.find({username:/test0123/});复制代码
大于等于、小于等于
//大于、大于等于、小于、小于等于 $lt, $lte, $gt, $gteselect * from user where age>=10 and age<=20db.user.find({ age:{$gte:10, $lte:20} });复制代码
等于null
select * from user where address is nulldb.user.find({ address: null });复制代码
不为null
select * from user where address is not nulldb.user.find({ address: {$ne:null} });复制代码
不为null 且不为""
select * from user where address is not null and address !=''db.user.find({ address: {$nin:[null,"" ]} });复制代码
in/not in
db.activity.find({ event: {$in:[50,60,70]} });db.activity.find({ event: {$nin:[50,60,70]} });复制代码
count
db.activity.find().count();db.activity.find({ event: {$in:[50,60,70]} }).count();复制代码
distinct
db.activity.distinct("user_name");复制代码
sort
db.getCollection("activity").find({type:10}).sort({createTime:1});复制代码
时间段
查询某个时间段的数据
db.activity.find({createTime:{$gte:ISODate('2020-03-01T00:00:00.000Z'), $lte:ISODate( '2020-03-11T00:00:00.000Z' )}});复制代码
聚合
聚合查询
MongoDB中聚合(aggregate)主要用于处理数据(求平局值、求和等),并返回计算后的数据结果。类似sql中的group。
$sum求和
按user_id分组,求每个用户订单总额
db.order.aggregate([{$group : {_id : "$user_id", total_order_money: {$sum : "$order_money"}}}])复制代码
$avg求平均值
按user_id分组,求每个用户订单平均支付金额
db.order.aggregate([{$group : {_id : "$user_id", avg_order_money: {$avg : "$order_money"}}}])复制代码
$min求最小值
按user_id分组,求每个用户订单最小支付金额
db.order.aggregate([{$group : {_id : "$user_id", min_order_money: {$min : "$order_money"}}}])复制代码
$max 求最大值
按user_id分组,求每个用户订单最大支付额
db.order.aggregate([{$group : {_id : "$user_id", max_order_money: {$max : "$order_money"}}}])复制代码
$push
按user_id分组,查看每个用户所有的支付方式(不去重)
db.order.aggregate([{$group : {_id : "$user_id", payMethods: {$push: "$pay_method"}}}])复制代码
$addToSet
按user_id分组,查看每个用户所有的支付方式(去重)
db.order.aggregate([{$group : {_id : "$user_id", payMethods: {$addToSet : "$pay_method"}}}])复制代码
$first
按user_id分组,求每个用户第一笔订单金额
db.order.aggregate([{$group : {_id : "$user_id", first_order_money : {$first : "$order_money"}}}])复制代码
$last
按user_id分组,求每个用户最后笔订单金额
db.order.aggregate([{$group : {_id : "$user_id", last_order_money: {$last : "$order_money"}}}])复制代码
聚合管道
聚合管道是 MongoDB 2.2版本引入的新功能。它由阶段(Stage)组成,文档在一个阶段处理完毕后,聚合管道会把处理结果传到下一个阶段。
聚合管道功能:
- 对文档进行过滤,查询出符合条件的文档
- 对文档进行变换,改变文档的输出形式
下图是官网给出的聚合管道的流程图:
上图中,match 为筛选条件,将符合条件的数据筛选出来传递给下一阶段 $group 中进行分组求和计算,最后返回 Results。其中,match、$group 都是阶段操作符,而阶段 $group 中用到的 $sum 是表达式操作符。
常用阶段操作符
实例1(聚合查询)
按user_id分组,求每个用户订单状态为20的订单平均金额
mysql:select user_id, avg(total_amount) from t_child_order where child_order_status=20group by merchant_code;mongo:db.t_child_order.aggregate( {$match:{child_order_status:20}} , {$group:{_id:"$user_id", avgDur:{$avg:"$total_amount" }} });复制代码
其中,match表示查询条件;match表示查询条件;match表示查询条件;group表示通过user_id分组,并计算user_id相同值的visit_duration的平均数据。
实例2 (管道操作)
需求: 统计2020-03-01至2020-04-18期间,活动ID为1239575334792146946,且操作时间为查看活动详情页面(event:10)该活动每天的访问PV、每天的平均访问时长、每天的访问用户集合。
db.activity.aggregate([ //条件,筛选出来的数据,传入到下一阶段 {"$match" : { "activity_id" : '1239575334792146946', "create_time" : { "$lte" : ISODate( '2020-04-18T00:00:00.000Z' ), "$gte" : ISODate('2020-03-01T00:00:00.000Z') }, "event" : 10} }, //设置数据列的展示规则,然后传入到下一阶段 { "$project" : { "create_time" : { "$dateToString" : { "format" : "%Y-%m-%d", "date" : "$create_time" } }, "visit_duration" : 1, "user_id" : 1 } }, //分组,计算数量、求和、求平均,然后传入到下一个阶段 { "$group" : { "_id" : "$create_time", "ALIAS_PAGE_PV" : { "$sum" : 1 }, "ALIAS_AVG_VISIT_DURATION" : { "$avg" : "$visit_duration" }, "ALIAS_USER_ARRAY" : { "$addToSet" : "$user_id" } } }, //设置结果是否展示 { "$project" : { "_id" : 0, "create_time" : "$_id", "ALIAS_PAGE_PV" : 1, "ALIAS_AVG_VISIT_DURATION" : 1, "ALIAS_USER_ARRAY" : 1, } }, //排序 { "$sort" : { "create_time" : -1 } } , //限制结果条数 {"$limit":3}] );复制代码
查询结果如图:
Map Reduce
Map-Reduce是一种计算模型,可对复杂的计算分解执行,然后将结果合并。
使用 MapReduce 要实现Map 函数和 Reduce 函数。
Map 函数调用 emit(key, value), 遍历 collection 中所有的记录, 将 key 与 value 传递给 Reduce 函数进行处理。
Map 函数必须调用 emit(key, value) 返回键值对。
db.collection.mapReduce( function() {emit(key,value);}, //map 函数 function(key,values) {return reduceFunction}, //reduce 函数 { out: collection, query: document, sort: document, limit: number })复制代码
- map :映射函数 (生成键值对序列,作为 reduce 函数参数)。
- reduce 统计函数,reduce函数的任务就是将key-values变成key-value,也就是把values数组变成一个单一的值value。。
- out 统计结果存放集合 (不指定则使用临时集合,在客户端断开后自动删除)。
- query 一个筛选条件,只有满足条件的文档才会调用map函数。(query。limit,sort可以随意组合)
- sort 和limit结合的sort排序参数(也是在发往map函数前给文档排序),可以优化分组机制
- limit 发往map函数的文档数量的上限(要是没有limit,单独使用sort的用处不大)
下图为MongoDB官网给出的Map-Reduce工作流程,从订单集合中,查找status为A的文档,按照cust_id分组,求每个cust_id的订单总额。
Map-Reduce使用实例
//统计每个用户的总访问时长db.activity.mapReduce( function() {emit(this.user_id, this.visit_duration);}, function(key, values) { return Array.sum(values) }, { query: { activity_id: "1236122613668032514", event:10 }, out:"temp_result" }).find();复制代码
//统计每个用户的平均访问时长db.activity.mapReduce( function() {emit(this.user_id, this.visit_duration);}, function(key, values) { var total= Array.sum(values); var sizes= values.length; return total/sizes }, { query: { activity_id: "1236122613668032514", event:10 }, out:"temp_result" }).find();复制代码
//统计每个用户的访问该页面的次数db.activity.mapReduce( function() {emit(this.user_id, 1);}, function(key, values) { return Array.sum(values)}, { query: { activity_id: "1236122613668032514", event:10 }, out:"temp_result" });db.temp_result.find();
mongodb 分组聚合_MongoDB干货总结相关推荐
- mongodb 分组聚合_mongodb 聚合命令
MongoDB中聚合主要用于处理数据,如统计平均值,求和等等,并返回计算后的数据结果. 1. count count函数返回指定集合中的数量. > db. mediaCollection.cou ...
- mongodb 分组聚合_MongoDB按键值对进行聚合/分组
我的数据看起来像这样: { "_id" : "9aa072e4-b706-47e6-9607-1a39e904a05a", "customerId&q ...
- mongodb 分组聚合_MongoDB学习笔记整理,赶紧收藏起来吧
mongodb是最近几年最火的nosql数据库,在很多大型企业应用广泛,今天就一起学习它的用法.花了一周时间,整理下面的学习记录,希望对大家有所帮助. mongodb 1. mongodb的安装, w ...
- mongodb 分组聚合_MongoDB聚合嵌套分组
我有资产收集,其中包含数据 { "_id" : ObjectId("5bfb962ee2a301554915"), "users" : [ ...
- MongoDB,分组,聚合
使用聚合,db.集合名.aggregate- 而不是find 管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数. MongoDB的聚合管道将MongoDB文档在一个管道处理 ...
- MongoDB多条件分组聚合查询
MongoDB多条件分组聚合查询 1.样例数据 {"_id" : ObjectId("5fa13fb76c3107345a82c047"),"_cla ...
- MongoDB的使用学习之(七)MongoDB的聚合查询(spring-data-mongodb两种方式)附项目源码
虽然只看了这一篇文章,但应该这个系列的文件应该都不错. http://www.cnblogs.com/ontheroad_lee/p/3756247.html 铛铛铛--项目源码下载地址:http:/ ...
- mongodb的聚合操作
mongodb的聚合操作 1 mongodb的聚合是什么 聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组.过滤等功 ...
- mongodb 聚合框架_如何使用MongoDB的聚合框架处理高级数据处理
mongodb 聚合框架 MongoDB has come a long way. Even though there are many NoSQL databases out there, Mong ...
最新文章
- 完美解决latex警告信息:Citation `Gusfield:97‘ on page 1 undefined.
- 在matlab中将处理结果输出为shp文件
- 李宏毅机器学习(十)GPT-3
- 【C语言】Simple Sorting(结构)
- 新书榜TOP 20占了17位!榜单里有哪些值得入手的技术新书?
- Linux下JDK和Tomcat安装
- [4G+5G专题-143]: 一体化小基站-硬件架构设计概述
- 【寻找最佳小程序】影视评分小工具“豆瓣评分”——产品设计要点及专家评析...
- (六)jmeter接口自动化难点系列---jmeter使用base64解密
- 道德经 道可道,非常道。
- 奇偶数判断(YZOJ-1032)
- Android 设置背景透明
- chrome cookie存在什么地方_谷歌浏览器产生的cookie缓存怎么查看呢?Cookie的具体内容在哪里...
- windows蓝屏代码含意全集
- 点击a标签,返回上一页
- java环境安装完毕,运行web项目报javax annotation managedbean unsup错误
- 〖Python 数据库开发实战 - MySQL篇⑯〗- SQL 语句的条件查询
- 【PDF】Adobe acrobat如何加注释
- 如何检测支付宝名字性别
- JDK源码系列:子线程如何继承父线程上通过ThreadLocal绑定的数据
热门文章
- java sort方法_Java排序方法sort用法详解
- mysql mysqld.log_MySQL mysqlbinlog 读取mysql-bin文件出错
- QT不同线程间signal-slot机制的值传递
- 互联网产品开发中的“快”字诀
- 通过HTTP的HEADER完成各种骚操作
- zabbix 自动发现
- Xshell利用密钥远程登录Linux
- 创建Windows Mobile上兼容性好的UI 程序
- 遇到了arcgis server9.1 在web开发的问题
- 分发服务器linux,Linux-LVS分发服务器