网站首页 > 基础教程 正文
什么是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(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
复制代码
- 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>
)
复制代码
- 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=3
db.spu.find({spu_name:"test0123", type:"3" });
复制代码
like
select * from user where username like "%test0123%"
db.user.find({username:/test0123/});
复制代码
大于等于、小于等于
//大于、大于等于、小于、小于等于 $lt, $lte, $gt, $gte
select * from user where age>=10 and age<=20
db.user.find({ age:{$gte:10, $lte:20} });
复制代码
等于null
select * from user where address is null
db.user.find({ address: null });
复制代码
不为null
select * from user where address is not null
db.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=20
group 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();
猜你喜欢
- 2024-10-29 57个挑战之57(part6):客户端+web前端+服务端代码实现
- 2024-10-29 技术干货|MongoDB数据库常见操作命令
- 2024-10-29 ABP vNext框架文档解读28-数据过滤
- 2024-10-29 自建MongoDB实践:MongoDB 分片集群
- 2024-10-29 小程序 随机读取数据并生成分享图片 上手笔记
- 2024-10-29 go-mongox:简单高效,让文档操作和 bson 数据构造更流畅
- 2024-10-29 当MongoDB遇见Spark mongodb campass
- 2024-10-29 MongoDB 5.0 官方文档学习笔记 mongodb教程
- 2024-10-29 好东西,MySQL 数据库 MongoDB详解
- 2024-10-29 MongoDB 入门 day04 mongodb27017
- 05-14CSS基础知识(一) CSS入门
- 05-14CSS是什么? CSS和HTML有什么关系?
- 05-14什么是CSS3?
- 05-14CSS如何画一个三角形?
- 05-14初识CSS——CSS三角制作
- 05-14Wordpress建站教程:给图片添加CSS样式
- 05-14HTML和HTML5,css和css3的区别有哪些?
- 05-14Html中Css样式Ⅱ
- 最近发表
- 标签列表
-
- jsp (69)
- pythonlist (60)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- mysql教程 (60)
- pythonif (86)
- location.href (69)
- deletesql (62)
- c++模板 (62)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- console.table (62)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)