前言

在上一篇文章中我们了解到了mongodb的基本操作,这一章我们更进一步继续来探讨mongodb,废话不多说,直接入正题吧。

mongodb的高级用法

聚合

mongodb中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的count(*).

例如现在有个需求,有一个保存这文章的集合,你可能希望找出发表文章最多的那个作者,假设每篇文章被保存为mongodb中的一个文档,这个需求我们怎么去实现呢?下面我们就一步一步的来实现这个需求。

aggregate()的用法

db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

假设集合中的数据如下:

{ "_id" : ObjectId("5a338a31ae83f6d96d3ef220"), "title" : "mongodb", "author" : "ck" }
{ "_id" : ObjectId("5a338a38ae83f6d96d3ef221"), "title" : "java", "author" : "ck" }
{ "_id" : ObjectId("5a338a4dae83f6d96d3ef222"), "title" : "node", "author" : "st" }
复制代码

首先我们先计算出每个作者缩写的文章数并排序,使用aggregate()计算结果如下所示:

> db.col.aggregate([{ $group: { _id: "$author", num: { $sum : 1 } } },{ $sort : { "_id":1 } }])
{ "_id" : "ck", "num" : 2 }
{ "_id" : "st", "num" : 1 }
复制代码

直接一步到位的如下所示:

> db.col.aggregate([{ $group: { _id: "$author", num: { $sum : 1 } } },{ $sort : { "_id":1 } }, { $limit:1 }])
{ "_id" : "ck", "num" : 2 }
复制代码

下表展示了一些聚合的表达式:

表达式 描述 实例
$sum 计算总和 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])。
$avg 计算平均值 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$min 获取集合中所有文档对应值得最小值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])。
$max 获取集合中所有文档对应值得最大值 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push 在结果文档中插入值到一个数组中。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet 在结果文档中插入值到一个数组中,但不创建副本。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first 根据资源文档的排序获取第一个文档数据。 db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])。
$last 根据资源文档的排序获取最后一个文档数据 db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])
管道的概念

管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。 MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。 表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。 这里我们介绍一下聚合框架中常用的几个操作:

$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。

$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。

$limit:用来限制MongoDB聚合管道返回的文档数。

$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。

$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。

$group:将集合中的文档分组,可用于统计结果。

$sort:将输入文档排序后输出。

$geoNear:输出接近某一地理位置的有序文档。

管道操作符实例

1、$project实例

db.article.aggregate({ $project : {title : 1 ,author : 1 ,}});
复制代码

这样的话结果中就只还有_id,tilte和author三个字段了,默认情况下_id字段是被包含的,如果要想不包含_id话可以这样:

db.article.aggregate({ $project : {_id : 0 ,title : 1 ,author : 1}});
复制代码

2.$match实例

db.articles.aggregate( [{ $match : { score : { $gt : 70, $lte : 90 } } },{ $group: { _id: null, count: { $sum: 1 } } }] );
复制代码

$match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理。

3.$skip实例

db.article.aggregate({ $skip : 5 });
复制代码

经过$skip管道操作符处理后,前五个文档被"过滤"掉。

复制(副本集)

复制集简介

目前我们一直使用的是单台服务器,一个mongod服务器进程。如果只是用作学习和开发,这是可以的,但是如果用到生产环境中,风险会很高。如果服务器崩溃了或者不可访问了怎么办?数据库至少会有一段时间不可用。如果是硬件除了问题,可能需要将数据转移到另一个机器上。在最坏的情况下,磁盘或者网络问题可能会导致数据损坏或者数据不可访问。

使用复制可以将数据副本保存到多台服务器上,建议在所有的生产环境中都要使用。使用mongodb的复制功能,即使一台或多台服务器出错,也可以保证应用程序正常运行和数据安全。

复制集功能

保障数据的安全性

数据高可用性

灾难恢复

无需停机维护(如备份, 重建索引, 压缩)

分布式读取数据

复制集特性

1.数据的一致性:主节点是唯一的,没有mysql那样的双主结构,如果当前主节点出现故障后,集群会自动容灾,通过选举,来选举出来一个合适的从节点来充当新的主节点,所以主节点是唯一的,但不是固定的。

2.大多数原则:集群存货节点小于等于二分之一时集群则不可写,只可读。如果复制集的服务器挂了一般就没法选举了,将全部将为从节点。

3.从库无法写入:只有主节点可写入数据,从节点只可读。

关于复制集以及下面的分片这一块,想深入研究的同学可以自行学习,原谅我只是个前端,哈哈。。

分片

分片简介

分片是指将数据拆分,将其分散存放在不同的机器上的过程。有时也用分区来表示这个概念。将数据分散到不同的机器上,不需要功能强大的大型计算机就可以存储更多的数据,处理更大的负载。

几乎所有数据库软件都能进行手动分片。应用需要维护与若干不同数据服务器的链接,每个链接还是完全独立的。应用程序管理不同服务器上不同数据的存储,还管理在合适的数据上查询数据的工作。这种方法可以很好的工作,但是非常难以维护,比如向集群添加节点或从集群删除节点都很款南,调整数据分布和负载模式也不轻松。

mongodb支持自动分片,可以使数据库架构对应用程序不可见,也可以简化系统管理。对应用程序而言,好像始终在使用一个单机的mongodb服务器一样。另一方面,mongodb自动处理数据在分片上的分部,也更容易添加和删除分片。

不管从开发角度还是运营角度来说,分片都是最困难最复杂的mongodb配置方式。

理解集群的组件

mongodb的分片机制允许你创建一个包含许多台机器(分片)的集群,将数据子集分散在集群中,每个分片维护者一个数据集合的子集。与单机服务器和副本集相比,使用集群架构可以使应用程序具有更大的数据处理能力。

这里有一点要注意,许多人可能会混淆复制和分片的概念。记住,复制是让多台服务器都拥有同样的数据副本,每一台服务器都是其他服务器的镜像,而每一个分片都有其他分片拥有不同的数据子集。

分片的目标之一是创建一个拥有5台、10台甚至1000台机器的集群,整个集群对应用程序来说就像是一台单机服务器。为了对应用程序隐藏数据库架构的细节,在分片之前要先执行mongos进行一次路由过程。这个路由服务器维护着一个“内容列表”,指明了每个分片包含什么数据内容。应用程序只需要连接到路由服务器,就可以像使用单机服务器一样进行正常的请求了,如下图所示。路由服务器知道哪些数据位于哪个分片,可以将请求转发给相应的分片。每个分片对请求的相应都会发送给路由服务器,路由服务器将所有相应合并在一起,返回给应用程序。对应用程序来说,它只知道自己是连接到了一台单机mongod服务器,如下图所示:

mongodb的安全加固

众所周知,数据安全非常重要,那么我们应该怎么对我们的mongodb进行安全加固呢?

修改默认端口

修改默认的mongodb端口(默认为:27017)为其他端口。

不要把mongodb服务器直接部署在外网上

1.通过安全组防火墙或服务器操作系统配置的防火墙对访问源IP进行控制,如果仅对内网服务器提供服务,建议禁止将mongodb服务发布到互联网上。

使用—bind_ip选项。

该选项可以限制监听接口IP,当在启动mongodb的时候,使用 --bind_ip 192.168.0.1 表示启动IP地址绑定,数据库实例将只监听192.168.0.1的请求。

启动基于角色的登录认证功能。

在admin数据库中创建用户,如用户名supper,密码supWDxsf67%H(此处为举例说明,请勿使用此账号密码)。

1.在未开启认证的环境下,登录到数据库。

> [mongodb@rac3 bin]$ ./mongo 127.0.0.1:27028 (此处修改了默认端口)
MongoDB shell version: 2.0.1
connecting to: 127.0.0.1:27028/test
复制代码

2.切换到admin数据库

> use admin
switched to db admin
复制代码

3.创建管理员账号

> db.addUser("supper", "supWDxsf67%H")或
> db.createUser({user:"supper",pwd:"supWDxsf67%H",roles:["root"]})
{ "n" : 0, "connectionId" : 4, "err" : null, "ok" : 1 }
{
"user" : "supper",
"readOnly" : false,
"pwd" : "51a481f72b8b8218df9fee50b3737c44",
"_id" : ObjectId("4f2bc0d357a309043c6947a4")
}
复制代码

管理员账号将在system.users中。

> db.getCollectionNames()
[ "system.indexes", "system.users", "system.version" ]
复制代码

说明:

mongodb从v3版本开始取消使用addUser方法,采用db.createUser方法创建用户;

账号不要设置为常见账号,密码需要满足一定的复杂度,长度至少八位以上,并包括大小写字母、数字、特殊字符混合体,不要使用生日、姓名、身份证编号等常见密码。

4.验证用户是否创建成功。

> db.auth("supper","supWDxsf67%H")
> exit "system.version" ]
bye
复制代码

5.结束进程,重启MongoDB服务。

> ./mongod --dbpath=/path/mongodb --bind_ip=192.168.0.1 --port=27028 --fork=true logpath=/path/mongod.log &
复制代码

说明:

    • admin.system.users中将会保存比在其它数据库中设置的用户权限更大的用户信息,拥有超级权限,也就是说在admin中创建的用户可以对mongodb中的其他数据库数据进行操作。
    • MongoDB系统中,数据库是由超级用户来创建的,一个数据库可以包含多个用户,一个用户只能在一个数据库下,不同数据库中的用户可以同名。
    • 特定数据库(比如DB1)的用户User1,不能够访问其他数据库DB2,但是可以访问本数据库下其他用户创建的数据。
    • 不同数据库中同名的用户不能够登录其他数据库,比如DB1、DB2都有user1,以user1登录DB1后,不能够登录到DB2进行数据库操作。
    • 在admin数据库创建的用户具有超级权限,可以对mongodb系统内的任何数据库的数据对象进行操作。
    • 使用db.auth()可以对数据库中的用户进行验证,如果验证成功则返回1,否则返回0。 db.auth()只能针对登录用户所属的数据库的用户信息进行验证,不能验证其他数据库的用户信息。
禁用HTTP和REST端口。

MongoDB自身带有一个HTTP服务和并支持REST接口(在V2.6以后这些接口默认是关闭的)。MongoDB默认使用默认端口监听Web服务,一般不需要通过Web方式进行远程管理,建议禁用。 修改配置文件或在启动的时候选择–nohttpinterface参数即可。

nohttpinterface = false
复制代码
开启日志审计功能。

审计功能可以用来记录用户对数据库的所有相关操作。这些记录可以让系统管理员在需要的时候分析数据库在什么时段发生了什么事情。

使用SSL加密功能。

MongoDB集群之间以及从客户端连接到MongoDB实例的连接应该使用SSL。使用SSL对性能没有影响并且可以防范类似于man-in-the-middle的攻击。

注意MongoDB社区版默认并不支持SSL。您可以选用MongoDB企业版(支持SSL),或者从源码重新编译MongoDB并使用—ssl选项来获得SSL功能。

以上所有配置,推荐以配置文件形式保存配置。

[mongodb@rac3 bin]$ vim /path/mongod.conf
port=27028-------端口。默认为27017端口,MongoDB的默认服务TCP端口,监听客户端连接。要是端口设置小于1024,比如1021,则需要root权限启动,不能用mongodb帐号启动,(普通帐号即使是27017也起不来)否则报错:[mongo --port=1021 连接]
bind_ip=192.168.0.1------绑定地址。默认127.0.0.1,只能通过本地连接。进程绑定和监听来自这个地址上的应用连接。要是需要给其他服务器连接,则需要注释掉这个或则把IP改成本机地址,如192.168.200.201[其他服务器用 mongo --host=192.168.200.201 连接] ,可以用一个逗号分隔的列表绑定多个IP地址。
logpath=/path/mongod.log------开启日志审计功能,此项为日志文件路径,可以自定义指定。
pidfilepath=/path/mongod.pid------进程ID,没有指定则启动时候就没有PID文件。
auth=true------用户认证,默认false。不需要认证。当设置为true时候,进入数据库需要auth验证,当数据库里没有用户,则不需要验证也可以操作。直到创建了第一个用户,之后操作都需要验证。
logappend=true------写日志的模式:设置为true为追加。默认是覆盖。如果未指定此设置,启动时MongoDB的将覆盖现有的日志文件。
fork=true------是否后台运行,设置为true 启动 进程在后台运行的守护进程模式。默认false。
nohttpinterface = false------是否禁止http接口,即28017 端口开启的服务。默认false,支持。
复制代码

然后,启动MongoDB服务时加载配置文件。

[mongodb@rac3 bin]$ ./mongod -f /path/mongod.conf
复制代码
对业务关键敏感数据进行加密存储。

建议您梳理业务数据,对关键的敏感数据加密后入库,例如:账号、密码、邮箱地址、手机号码、身份ID等其他数据。加密算法推荐选择国际通用加密算法和多次加盐组合自定义算法,防止加密算法被破解。

即使黑客获取数据后,也查看不了数据,通过“看不懂”的数据加密方式将损失降到最低。

对数据进行本地异地备份。

完善的备份策略是保证数据安全的最后一根救命稻草。

推荐:可靠的本地备份+远程备份存储方案

本地备份

1.MongoDB备份方式

>mongodump -h dbhost -d dbname -o dbdirectory
-h:
MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
-d:
需要备份的数据库实例,例如:test
-o:
备份的数据存放位置,例如:c:\data\dump,该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。
复制代码

2.MongoDB数据恢复

mongodb使用 mongorestore 命令来恢复备份的数据。
语法
mongorestore命令脚本语法如下:
>mongorestore -h dbhost -d dbname --directoryperdb dbdirectory
-h:
MongoDB所在服务器地址
-d:
需要恢复的数据库实例,例如:test,这个名称也可以和备份时候的不一样,比如test2。
--directoryperdb:
备份数据所在位置,例如:c:\data\dump\test。
--drop:
恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用!
复制代码

3.Mongodump命令可选参数列表如下所示。

语法 描述 实例
mongodump --host HOST_NAME --port PORT_NUMBER 该命令将备份所有mongodb数据 mongodump --host w3cschool.cc --port 27017
mongodump --dbpath DB_PATH --out BACKUP_DIRECTORY mongodump --dbpath /data/db/ --out /data/backup
mongodump --collection COLLECTION --db DB_NAME 该命令将备份指定数据库的集合 mongodump --collection mycol --db test

4.备份策略

全量备份:可以最快的时间快速恢复所有数据,缺点是备份成本大,时间长

全量备份+增量备份:可以较快的恢复所有数据,缺点是恢复时间长,如果增量数据有问题,无法恢复所有数据。

搭建从库:直接切换到从库,前提是从库的数据安全可靠。

欢迎各路大佬对文章错误的地方进行指正,万分感谢,共同学习进步。博主的GitHub地址,可以在GitHub提Issues或者直接在文章下面评论区留言。

关于mongodb的学习与探索二相关推荐

  1. 尚硅谷+黑马程序员MongoDB视频学习笔记(一)

    本学习笔记是来源于学习B站上的尚硅谷和黑马的MongoDB教学视频而做的知识总结. 一.数据库(Database) 数据库是按照数据结构来组织.存在和管理数据的仓库.说白了,数据库就是存在数据的仓库. ...

  2. 【深度学习】DIY 人脸识别技术的探索(二)

    [深度学习]DIY 人脸识别技术的探索(二) 文章目录 训练模型 工具 结果展示 问题二的模型建立与求解 基于 KNN 的人脸识别模型 训练模型 MTCNN 可以并行训练(3 个网络同时训练,前提是内 ...

  3. Mongodb使用学习笔记(二)

    文章目录 Mongodb使用学习笔记(二)之查询篇 1. MongoDB命令学习 (1) MongoDB 查询文档 1.1 全部查询 1.2 单条件查询 1.3 多条件查询 1.3.1 AND拼接多条 ...

  4. MongoDB开发学习开天辟地,经典入门

    如果你从来没有接触MongoDB或对MongoDB有一点了解,如果你是C#开发人员,那么你不妨花几分钟看看本文.本文将一步一步带您轻松入门. 阅读目录 一:简介 二:特点 三:下载安装和开启服务器 四 ...

  5. 卷积神经网络学习路线(二十一) | 旷世科技 ECCV 2018 ShuffleNet V2

    前言 这个系列已经更新了20多篇了,感谢一直以来大家的支持和等待.前面已经介绍过MobileNet V1,MobileNet V2,MobileNet V3,ShuffleNet V1这几个针对移动端 ...

  6. 《计算广告》学习笔记(二)

    <计算广告>学习笔记(二) 第三章:在线广告产品概述 3.1商业产品的设计原则 3.2广告系统的产品接口 第四章:合约广告 4.1广告位合约 4.2受众定向 4.2.1受众定向方法概览 4 ...

  7. mongodb的学习记录

    node.js中的mongodb的学习记录: //1.创建并进入it_like数据库 use itlike db//2.向数据库的colleges集合中插入六个文档(Html5, Java, Pyth ...

  8. 产品经理—开发转产品,浅谈自我学习与探索

    编辑导语:如今有越来越多人正想着入职产品岗位,产品经理不论出生,人人都是产品经理,然而想做好产品经理也绝非易事.本文讲述了作者从开发转向产品岗位的背景.想法.学习和探索过程的些许经验,亦或是对自己转行 ...

  9. 股票操作之强化学习基础(二)(Q-learning、Sarsa、Sarsa-lambda)

    股票操作之强化学习基础(二)(Q-learning.Sarsa.Sarsa-lambda) 1. Q-learning Q-learning是强化学习一个比较基础的算法,很多强化学习的升级算法都是在q ...

  10. Java后端学习日记(二):POJO的基本概念,编写,转化和简化

    专栏目录 Java后端学习日记(一):第一个Springboot应用--Hello World! Java后端学习日记(二):POJO的基本概念,编写,转化和简化 Java后端学习日记(三):Spri ...

最新文章

  1. excel 打开显示安装office自定义项 安装期间出错
  2. Fedora 8中驱动ASUS6摄像头
  3. tf.arg_max
  4. SpringBoot Thymeleaf使用教程(实用版)
  5. python raise函数_Python raise用法
  6. 算法与数据结构(一)
  7. Honeycomb Gym - 102028F(bfs)
  8. esim办理出现差错_经营二氧化碳如何办理危化证?快来看!
  9. MySQL 基础 ———— 子查询
  10. uinty粒子系统子物体变大_Unity的粒子系统(一)基础篇
  11. 仿苹果手机闹钟_原来iPhone闹钟这么牛!用6年苹果今天才发现,以前不懂一直想删...
  12. php中%3c w() %3e,DedeCMS V5.7 SP2后台存在代码执行漏洞
  13. mid制作乐谱_乐谱编辑(在线简谱制作软件)
  14. access数据库为什么一直登陆_Access数据库创建用户登录
  15. uni-app 简介
  16. winzip15.0注册码
  17. SMSBMS超市订单管理系统详解(一:准备工作)
  18. CorelDRAW X8官方正版序列号如何安装使用?
  19. 分享电脑日常使用的小技巧
  20. 软硬整合:开发一款VR大作背后的技术支撑

热门文章

  1. Atitit office Ooxml excel标准的主要内容 目录 1.1. 物理存储 zip+文件夹包+xml 1 1.2. Package Structure 1 1.3. 内容部分 1
  2. qqzoneQQ空间漏洞扫描器的设计attilax总结
  3. atitit.DD dragdrop拖拽文件到界面功能 html5 web 跟个java swing c#.net c++ 的总结
  4. atitit.表格的绑定client side 最佳实践
  5. 学习笔记 | 读完《公开募集证券投资基金销售机构监督管理办法》的几点感受
  6. 梁勇:展望 2017年商业智能BI 发展的趋势
  7. 疫期免费 “零接触”云迁移~工具替代人力! 人不聚,活儿继续!
  8. 【车牌识别】基于matlab GUI模板匹配车牌识别【含Matlab源码 958期】
  9. 【图像修复】基于matlab GUI运动模糊消除(逆滤波)【含Matlab源码 847期】
  10. SPSS 项目分析(图文+数据集)【SPSS 032期】