开发者学堂课程【MongoDB 快速入门:走进 MongoDB】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/49/detail/1000
走进 MongoDB
内容介绍:
一、MongoDB 的概念
二、集群部署
三、MongoDB 的基本操作
一、MongoDB 的概念
1、概念
本节课学习走进 MongoDB,首先了解 MongoDB的概念,在定位方面 MongoDB介于Memcached 和关系数据库(RDBMS)之间,从扩展性和性能上讲 MongoDB更接近Memcached,从功能上讲MongoDB更接近关系数据库,在部署方面生态环境中MongoDB通常会被部署为一个高可用的复制集或者是一个分片集群。
先看左边的Replica Set,当MongoDB被部署为一个高可用的复制集时,应用程序根据MongoDB的驱动连接集群的主节点完成读写操作,这时两个从节点会自动与主节点同步完成数据更新。一旦主节点遇到故障,两个从节点会在很短的时间内选出新的主节点支持业务的读写请求。之后看右边的Shard Cluster,当MongoDB被部署为一个分片集群的时候,应用程序通过驱动连接集群中的MongoS节点,也就是路由节点,MongoS节点会根据片面的值把请求分发到对应的分片上,然后将分片的结果合并返回给应用程序,数据在各个分片的分布是原数据存储在Config集群,Config也是一个高可用的复制集。
2、MongoDB 基本概念与关系数据的对应关系
接下来学习MongoDB基本概念与关系数据库的对应关系,在关系与数据库里通常会有数据库和表的概念,对应的在MongoDB有数据库和集合,关系与数据库里面经常有主表和子表,对应的在MongoDB里面通常使用内嵌的子文档或者是内嵌数组来实现,关系与数据库里有index,所以MongoDB里面也有类似的概念,关系与数据库里面一条数据称为一行,对应的MongoDB里面称为Document文档,关系与数据库里面的列对应到MongoDB里面成为一个字段Field,关系与数据库里面经常使用join连接操作,对应的MongoDB里面使用内嵌的方式解决,如果使用Linking的话对应使用$lookup操作符也可以支持左外连接,关系与数据库里的视图对应的MongoDB里面有制度视图和按需物化视图,以及ACID的多文档事务,关系与数据库里有ACID的多记录事务对应的MongoDB里面有ACID的多文档事务。
3、MongoDB 的数据层次结构
MongoDB里面数据主要分为三层文档(Documents),集合(Collections),和数据库(Databases)三层,多个文档存储在一个集合当中,多个集合存放在一个数据库里面,在每个集群里面可能会有多个数据库,举个例子比如有一个产品的数据库products,在products里面会有多个集合,比如有存放书籍的books集合,还有存放电影和音乐的分别是movies和music两个集合,数据库和集合合起来就构成了一个集合的命名空间,比如products.books就是books这个集合的命名空间。
4、MongoDB 的数据结构
接下来学习MongoDB的数据结构,MongoDB采用JSON文档结构,在JSON里面通常支持字符串(eg“Thomas”)、数字(eg,29,3.7)、布尔(ture/false)、空值(null)、数组(eg,[88.5,91.3,67.1])和子的对象(object),在底层MongoDB采用BSON格式保存数据。目的是为了支持更丰富的数据结构。
5、MongoDB 数据类型
观察MongoDB数据列表可以发现,MongoDB支持Double双进度类型,还有String字符串类型,Object对象类型,Array数组,Binary data二进制类型,Objectld布尔类型,date日期等常见的类型MongoDB都支持
二、集群部署
1、安装 MongoDB 系统
接下来进行集群部署的学习,比如安装第一个MongoDB系统的时候需要做三步,第一步下载MongoDB的安装介质,以linux环境为例,比如可以使用curl命令去下载MongoDB最新版本的安装介质curl-O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.2.taz,下载完成之后第二个命令使用tar命令tar xzvf mongodb-linux-x86_64-rhel70-4.4.2.tgz进行压缩,解压之后可以改一个名字比如把前面比较长的改成MongoDB,mv mongodb-linux-x86_64-rhel70-4.4.2 mongodb。不需要其他命令整个安装部署就结束了。
2、启动 MongoDB 服务
启动MongoDB服务使用mongod进程,mongod是MongoDB的守护进程,对应的唯一需要的参数是dbpath,dbpath指定数据存放的目录,这样可以通过mongod命令带上参数dbpath指定对应的数据目录启动就可以。
3、通过客户端访问 MongoDB 的服务
通过客户端访问MongoDB的服务,可以使用同样安装目录下的Mongo命令,也就是mongo shell,通过mongo shell执行之后回车就可以了,默认不带其他参数的情况下,mongo shell会连上本机的27107端口。
4、创建复制集的步骤
创建一个三节点的复制集的具体步骤,第一步需要创建三个目录,比如创建mkdir rs1、 rs2 、rs3三个目录分别存放三个节点的数据,然后启动三个mongod的服务,第一个需要指定replSet也就是复制集的名称,这里指定为rs,--dbpath指定数据目录,三个命令分别指定rs1、rs2、rs3来作为三个进程的数据目录,因为想要将三个mongodb的进程都部署在一台服务器里面,所以要分别指定不同的端口,第一个用27017,后面的依次用27018、27019,--fork的意思是不block前端,让它在后台运行,--logpath是对应的MongoDB的日志写在什么地方,通过mongod--replSet rs--dbpath ./rs1--port 27017--fork--logpath./rs1/mongod.log,mongod--replSet rs--dbpath ./rs2--port 27018--fork--logpath./rs2/mongod.log,mongod--replSetrs--dbpath./rs3--port27019--fork--logpath./rs3/mongod.log三行命令可以启动三个mongod的服务,这就是第二个步骤。
第三个步骤使用mongo shell,mongo这个命令如果不带参数就会直接连接上本机的27017端口的进程。
第四步执行配置复制集的命令,首先执行rs.initiate这样可以初始化复制集,初始完复制集之后里面会包含一个节点就是本机的27107端口的进程节点,然后用rs.add分别去添加27018和27019另外两个节点,之后可以用rs.status查看整个集群有哪些节点以及节点的状态。这样整个复制集就部署完成。
5、创建分片集群的步骤
创建复制集群第一步要创建一个Config Server的复制集,具体步骤可以参考前面创建复制集的步骤,接下来需要创建一个或多个分片,每一个分片也是一个高可用的复制集,创建方式与前面创建复制集的方式类似,第三步启动mongos节点路由节点,mongos节点可以启动一个或多个,第四步要访问启动一个mongos节点,之后把创建的几个分片添加到集群中,最后一步选择合适的片键,然后对对应的数据库和集合启用分片。这样整个分片集群的部署就完成了。
6、生产环境部署建议
在生产环境中应该遵循生产环境部署的一些最佳实践,比如应该先进行容量规划,规划生产环境中具体的应用负载所需要计算资源、存储资源还有包括存储的IOPS,此外还有Oplog的大小,网络带宽的需要。另外生产环境当中建议部署一个高可用的复制集或者是分片集群, 节点个数在生产环境中节点个数应为奇数个, 这样可以避免网络脑裂的情况发生,此外还有一些其他生产环境的最佳实践,比如添加每个节点的时候都使用节点的主机名,而不是使用IP地址。以及选择合适的文件系统,比如在linux当中推荐使用XFS的文件系统, 建议禁用NUMA以及禁用THP。Linux里面通常也会对每个用户进程资源使用有限制 ,应该调高这个限制,以便获得更高的一个性能。此外还有swappiness,通常建议调成1,readahead也应该进行调整,通常建议调整到8-32之间,tcp_keepalive推荐设置成120秒,此外生产环境当中对于这样的分布式集群还应该用时钟同步确保各个节点之间的时间完全一致,生产环境中应启用安全建议。
三、MongoDB 的基本操作
1、插入新文档
首先看一下插入的操作,插入操作对应的命令有insert One 、insert Many和insert,可以使用insert One创建一个文档,把文档传给insert One,插入到数据库当中,这样就可以插入一个新的文档,insertMany可以去插入多个文档,一条操作插入多个文档,这里需要传入一个数组,数组的每个元素将来都会被插入成一个新的文档,此外还有insert命令,insert命令不分插入一个还是多个,主要取决于传入的参数,如果传入的是一个document 就插入一个文档。如果传入的是一个数字组,数组当中的每一个元素都会被插入成一个文档。
2、删除文档
再来看一下删除文档的操作,删除文档最常用的两个命令,一个是deleteOne,另一个是deletaMany。deleteOne删除匹配到的第一个文档,比如可以传入参数“_ID”和它对应的值,对应的文档就会被删掉。也可以传入一个条件,比如expiration就是过期时间,$it 表示小于某一个时间的一个条件,这样匹配到的第一个文档会被删除,如果想要删除多个文档,可以使用deleteMany,deleteMany可以传入一个查询条件,这样所有匹配到条件的文档都会被删除。此外还有一个remove的命令,也可以帮助删除文档。删除集合的时候 可以使用drop命令,比如db.<COLLECTION>.drop会删除掉整个集合, 这样集合当中的文档都被删除,此外集合里面存在的索引也会被删除。删除数据库可以使用drop database,比如可以使用来db.dropDatabase删除当前的数据库,数据库相应的文件也会被删除,对应的磁盘空间也会释放。
3、使用 find 查询数据文档
使用find查找所需要的数据文档,find是MongoDB基础的查询命令,它会返回cursor,也就是游标。比如可以使用db.movies.find({“year”:1979})根据年份year=1975单条件进行查询,或者是year等于1989加上另外一个条件 比如说title等于batman多条件来进行查询,即db.movies.find({“year”:1989,“title”:“Batman”})。当不加$or或者$and表示这些条件之间关系的时候,默认使用$and, 也就是多个条件之间是与的关系,此外还可以使用$or,表示两个条件之间是或的关系。还可以显示的使用$and,此外还可以使用正则表达式查询。
4、SQL 查询条件对照
对应的可以看一下SQL的查询条件与mongoDB之间的对照关系,比如SQL里面常用a=1,对应的在mongoDB里面是{a:1}。还有不等于、大于等于,这些在mongoDB里面都有对应的查询字据,以及刚才提到的and和or这些关系,对应的在mongoDB是$and和$or两个操作符。在关系与数据库里面会使用某一个字段,比如a IS NULL就是这个字段的值是空的,对应的mongoDB里面使用{a:{$exists:false}},也就是这个字段不存在用这样的条件进行过滤,还有$in这样的操作符。
5、查询操作符
为了便于记忆刚刚讲过的操作符,进行简单的解释,比如$lt原来的英文单词是less than也就是小于,$lte是less than or equal也就是小于或等于,$ge对应的是great than大于,$gte表示great than or equal大于或者等于,$ne表示not equal不存在或存在但不等于,还有$in存在并在指定数组中,$nin表示not in不存在或不在指定数组中,以及$or匹配两个或多个条件中的一个,$and匹配全部条件。
6、更新操作
再来学习一下更新的操作,更新操作使用update命令进行执行,update命令里包括两个参数一个是条件查询的条件,也就是有哪些文档进行更新,另外一个是更新的参数,比如可以看到的是db.movies.update({“title”:“Batman”},{$set:{“imdb_rating”:7.7}})即在movies表里面插入一些实例数据,update命令里面指定的查询条件是title=Batman,更新字段用$set去指定更新的字段,比如这里是“imdb_rating”更新为7.7。
默认情况下update命令会更新一条记录,如果想要更新多条记录可以增加参数multi:true。MongoDB里面数组是一个很常用的数据类型,更新数组有一些常用的操作符,比如$push是增加一个元素到数组的底部,$pushAll是增加多个元素,$pop会从数组的底部删除掉一个元素,还有 $pull和$pullAl l会按照指定条件从数组中删除对应的元素,以及常用的 $addToSet 会在增加元素的时候检查是否会从数组中存在相应的元素,如果存在的话就不增加,如果不存在的话就进行添加。
7、使用{upsert:true}更新或插入
此外如果想根据条件有匹配到的文档就进行 update 的操作,没有匹配到的就进行插入操作,如果有这样的需求可以加上参数 upsert=true。这样如果没有匹配到的元素就会进行 insert 操作,如果有就会进行 update 的操作。