MongoDB是一个基于分布式文件存储的数据库,由C++措辞编写,旨在为Web运用供应可扩展的高性能数据存储办理方案。
MongoDB是一个介于关系数据库和非关系数据库之间的数据库。它支持的数据构造非常疏松,类似JSON的BSON格式,因此可以存储比较繁芜的数据类型。
MongoDB最大的特点是它支持的查询措辞非常强大,其语法有点类似于面向工具的查询措辞,险些可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
一 凑集与文档
MongoDB是“面向凑集”(Collection-Oriented)进行设计的,数据库中的数据被分组存储在不同的数据凑集(Collection)中。每个凑集在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档(Document)。
凑集的观点类似关系数据库(RDBMS)中的表(Table),不同的是它不须要定义任何模式(schema)。向表中写入数据前必须提前定义表构造,而向凑集中写入数据前不须要限定凑集的构造,这被称为模式自由(schemafree),这意味着对付存储在MongoDB数据库中的文件,不须要知道它的任何构造定义。如果须要的话,完备可以把不同构造的文件存储在同一个数据库里。
写入表中的数据被称为记录行,而写入凑集中的数据被称为文档。
存储在凑集中的文档,被存储为键/值对的形式。键用于唯一标识一个文档,为字符串类型;而值则可以是各种繁芜的文件类型(如整形、日期型),这种存储形式被称为BSON(Binary Serialized Document Format)。
下面详细先容一下MongoDB中的文档与凑集的基本观点。
(1)文档。
文档是MongoDB中数据的基本单位,类似于关系数据库中的行(但是比行繁芜)。多个键及其关联的值有序地放在一起就构成了文档。不同的编程措辞对文档的表示方法不同,在JavaScript中文档表示为:
{"greeting":"hello,world"}
这个文档只有一个键"greeting",对应的值为"hello, world"。多数情形下,文档比这个更繁芜,它包含多个键/值对。例如:
{"greeting":"hello,world","foo": 3}
文档中的键/值对是有序的,下面的文档与上面的文档是两个完备不同的文档。
{"foo": 3,"greeting":"hello,world"}
文档中的值不仅可以是双引号中的字符串,也可以是其他的数据类型,如整型、布尔型、日期型等,还可以是其余一个文档,即文档可以嵌套。文档中的键类型只能是字符串类型。
(2)凑集。
凑集便是一组文档,类似于关系数据库中的表。凑集是无模式的,凑集中的文档可以是各式各样的。例如,{"hello,word":"Mike"}和{"foo": 3},
它们的键不同,值的类型也不同,但是它们可以存放在同一个凑集中,也便是不同模式的文档可以放在同一个凑集中。
既然凑集中可以存放任何类型的文档,那么为什么还须要利用多个凑集?这是由于所有文档都放在同一个凑集中,无论对付开拓者还是管理员,都很难对凑集进行管理,而且这种环境下,对凑集的查询等操作效率很低。以是在实际利用中,每每将文档分类存放在不同的凑集中,例如,对付网站的日志记录,可以根据日志的级别进行存储,Info级别日志存放在Info凑集中,Debug级别日志存放在Debug凑集中,这样既方便了管理,也提高了查询性能。但是须要把稳的是,这种对文档进行划分来分别存储并不是MongoDB的逼迫哀求,用户可以灵巧选择。
可以利用“.”按照命名空间将凑集划分为子凑集。例如,对付一个博客系统,可能包括blog.user和blog.article两个子凑集,但这样划分只是让组织构造更清晰一些,blog凑集和blog.user、blog.article没有任何关系。虽然子凑集没有任何分外的地方,但是利用子凑集组织数据构造会更清晰,这也是MongoDB推举的方法。
二 MongoDB运用处景MongoDB的设计目标是高性能、可扩展、易支配、易利用,利用它存储数据非常方便。其紧张功能特性如下。
(1)面向凑集存储,随意马虎存储工具类型的数据。在MongoDB中数据被分组存储在凑集中,凑集类似RDBMS中的表,一个凑集中可以存储无限多的文档。
(2)模式自由,采取无模式构造存储。在MongoDB凑集中存储的数据是无模式的文档,采取无模式存储数据是凑集差异于RDBMS中的表的一个主要特色。
(3)支持完备索引,可以在任意属性上建立索引,包含内部工具。
MongoDB的索引和RDBMS的索引基本一样,可以在指定属性、内部工具上创建索引以提高查询的速率。除此之外,MongoDB还供应创建基于地理空间的索引的能力。
(4)支持查询。MongoDB支持丰富的查询操作,MongoDB险些支持SQL中的大部分查询。
(5)强大的聚合工具。MongoDB除了供应丰富的查询功能外,还供应强大的聚合工具,如count、group等,支持利用MapReduce完成繁芜的聚合任务。
(6)支持复制和数据规复。MongoDB支持主从复制机制,可以实现数据备份、故障规复、读扩展等功能。而基于副本集的复制机制供应了自动故障规复的功能,确保了集群数据不会丢失。
(7)利用高效的二进制数据存储,包括大型工具(如视频)。利用二进制格式存储,可以保存任何类型的数据工具。
(8)自动处理分片,以支持云打算层次的扩展。MongoDB支持集群自动切分数据,对数据进行分片可以使集群存储更多的数据,实现更大的负载,也能担保存储的负载均衡。
(9)支持Perl、PHP、Java、C#、JavaScript、Ruby、C和C++措辞的驱动程序,MongoDB供应了当前所有主流开拓措辞的数据库驱动包,开拓职员利用任何一种主流开拓措辞都可以轻松编程,实现MongoDB数据库的访问。
(10)文件存储格式为BSON(JSON的一种扩展)。BSON是二进制格式的JSON的简称,BSON支持文档和数组的嵌套。
(11)可以通过网络访问。可以通过网络远程访问MongoDB数据库。MongoDB的紧张目标是通过键/值存储办法(供应了高性能和高度伸缩性)和传统的RDBMS系统之间架起一座桥梁,它集两者的上风于一身。
根据官方网站的描述,MongoDB适用于以了局景。
· 网站数据:MongoDB非常适宜实时地插入、更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
· 缓存:由于性能很高,MongoDB也适宜作为信息根本举动步伐的缓存层。在系统重启之后,由MongoDB搭建的持久化缓存层可以避免下层的数据源过载。
· 大尺寸、低代价的数据:利用传统的关系数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员每每会选择传统的文件进行存储。
· 高伸缩性的场景:MongoDB非常适宜由数十或数百台做事器组成数据库集群,MongoDB的路线图中已经包含对MapReduce引擎的内置支持。
· 用于工具及JSON数据的存储:MongoDB的BSON数据格式非常适宜文档化格式的存储及查询。
MongoDB的利用也会有一些限定,例如,它不适宜于以下几种运用处景。
· 高度事务性的系统:例如,银行或司帐系统。传统的关系数据库目前还是更适用于须要大量原子性繁芜事务的运用程序。
· 传统的商业智能运用:针对特定问题的BI数据库会产生高度优化的查询办法。对付此类运用,数据仓库可能是更得当的选择。
· 须要SQL的场景。
三 MongoDB下载与安装MongoDB目标安装环境为CentOS7,安装步骤如下。
(1)安装包下载。
从MongoDB官网(https://www.MongoDB.com/try/download/community)
下载Linux环境下的安装包MongoDB-linux-x86_64-rhel70-4.2.12.tgz。
(2)利用xftp上传安装包到/usr/local目录下,然后解压。
(3)在MongoDB目录下,创建data和logs文件夹。
(4)后台启动MongoDB做事(默认只许可本机客户端连接)。
(5)客户端连接做事器(如图6-1所示)。
图6-1 MongoDB做事启动与连接
(6)重新启动做事器,许可采取远程IP办法连接做事器。
MongoDB的启动参数如表6-1所示。
表6-1 MongoDB启动参数
表6-1 MongoDB启动参数
四 系统数据库与用户库MongoDB中多个文档组成凑集,多个凑集组成数据库。一个MongoDB实例可以承载多个数据库,每个数据库相对独立,都有自己的权限掌握。
在磁盘上,不同的数据库存放在不同的文件中。MongoDB中存在的系统数据库有:admin,local,config,用户还可以创建属于自己的数据库。
· admin数据库:一个权限数据库,如果创建用户的时候将该用户添加到admin数据库中,那么该用户就自动继续所有数据库的权限。
· local数据库:这个数据库永久不会被复制,可以用来存储本地单台做事器的任意凑集。
· config数据库:当MongoDB利用分片模式时,config数据库在内部利用,用于保存分片的信息。
客户端连接MongoDB数据库后,可以创建属于自己的用户数据库(如图6-2所示)。
图6-2 系统数据库与用户数据库
五 权限管理角色是身份的象征,同时也是权限的识别。MongoDB中内置了如下多种角色。
· read:许可用户读取指天命据库。
· readWrite:许可用户读写指天命据库。
· dbAdmin:许可用户在指天命据库中实行管理函数,如索引创建、删除,查看统计或访问system.profile。
· userAdmin:许可用户向system.users凑集写入,可以在指天命据库里创建、删除和管理用户。
· clusterAdmin:只在admin数据库中可用,授予用户所有分片和复制集干系函数的管理权限。
· readAnyDatabase:只在admin数据库中可用,授予用户所有数据库的读权限。
· readWriteAnyDatabase:只在admin数据库中可用,授予用户所有数据库的读写权限。
· userAdminAnyDatabase:只在admin数据库中可用,授予用户所有数据库的userAdmin权限。
· dbAdminAnyDatabase:只在admin数据库中可用,授予用户所有数据库的dbAdmin权限。
· root:只在admin数据库中可用。超级账号,超级权限。
作为普通用户,一样平常会拥有read和readWrite角色。而数据库管理员,会拥 有 dbAdmin 、 dbOwner 、 userAdmin 等 角 色 。 集 群 管 理 员 可 以 有clusterAdmin、clusterManager、clusterMonitor、hostManager等角色。备份管理员可以有backup、restore等角色。
创建用户时,须要给用户赋权,便是指定用户有何种角色。当然,可以许可一个用户同时拥有多种角色。把稳:用户属于库,给某个数据库创建用户时,必须要先打开该数据库。
示例:在admin数据库下,创建系统管理员(如图6-3所示)。
图6-3 创建系统管理员
示例:在mydb库下,创建普通用户(如图6-4所示)。
图6-4 创建普通用户
示例:用户登录与权限掌握,操作步骤如下。
(1)重新启动MongoDB开启用户权限校验模式:
(2)客户端远程访问MongoDB。
(3)开启授权模式后,打开admin数据库,只有利用管理员权限的用户才能查询数据库和用户信息(如图6-5所示)。
(4)打开mydb数据库,只有授权的普通用户才能操作(如图6-6所示)。把稳:同一个客户端只能有一个用户登录,以是管理员与普通用户该当利用两个客户端。
图6-5 管理员登录
图6-6 普通用户登录
六 文档的CRUD操作
MongoDB是完备模式自由的,即类型完备不同的文档可以存放在同一个凑集中。但是在实际开拓中,同一个凑集中的数据只管即便存放相同类型的文档数据,这样更便于数据检索和数据掩护。文档的CRUD(增编削查)操作示例如下。
(1)新建user凑集,插入用户数据
(2)查询新建user凑集与凑集中的数据。
(3)利用循环向凑集中插入数据。
(4)删除凑集中复合条件的文档。
(5)修正文档。
(6)条件查询。
查询条件中在碰着分外符号时,须要利用转义符,$lt表示<,$lte表示<=,$gt表示>,$gte表示>=,$ne表示!=;$in表示范围内,$nin表示不在范围内。
(7)删除凑集。
七 内嵌文档
在关系数据库中,表与表之间存在着一对一、一对多、多对一、多对多等关系。通过表之间的关系,可以进行多表联合的SQL查询(外键关联)检索数据。
在MongoDB中凑集模式是完备自由的,不存在凑集与凑集之间的关系。当涌现如了局景时,如何存储数据呢?
一个用户有多个邮寄地址、一个用户有多个电话、一个用户有多种角色信息、一个用户有一个购物车、一个用户对应一个员工等。
MongoDB的办理方案是推举利用内嵌文档来表示文档与文档之间的一对一和一对多的关系。
创建内嵌文档操作示例如下。
内嵌文档查询示例如下。
内嵌文档内容修正示例如下。
向内嵌文档中插入新数据的示例如下。
订单与订单明细内嵌文档操作步骤如下。
(1)创建两条新订单(订单明细为内嵌文档)。
(2)订单检索。
(3)添加订单明细(如图6-7所示)。
图6-7 添加订单明细
(4)删除一条订单明细。
八 索引
关系数据库如MySQL、Oracle,当记录数超过几万条时就须要考虑利用索引来提高检索速率。从数据构造上划分,MySQL支持B+树或哈希索引;从逻辑上划分,MySQL目前紧张有以下几种索引类型:普通索引;唯一索引;主键索引;联合索引;全文索引。
从MySQL 5.5往后,InnoDB是默认引擎。在MySQL innoDB引擎中,主键索引又被称为聚簇索引(叶子数据区中含有所有真实的数据)。
Oracle中还有位图索引,它特定用于该列只有几个列举值的情形,比如性别字段、省份字段、订单状态等字段都可以建立位图索引。
MongoDB支持多种类型的索引,如普通索引、联合索引、唯一索引、全文索引等,每种类型的索引有不同的利用场合。
创建普通索引示例(如图6-8所示)如下。
把稳:凑集中的文档都会有一个名为_id的默认键,该键会被自动创建索引。
删除索引示例如下。
创建唯一索引示例(如图6-9所示)如下。
创建联合索引示例(如图6-10所示)如下。
图6-8 凑集中的普通索引
图6-9 唯一索引
图6-10 联合索引
创建全文索引示例如下。
把稳:MongoDB对付中文的分词搜索支持得不好,请谨慎利用。
(1)新增3个用户,用户名中间有空格。
(2)创建全文索引。
(3)利用全文索引进行分词查询(如图6-11所示)。
图6-11 全文索引进行分词查询
九 查询剖析在MongoDB进行条件查询时,调用explain()方法,即可进行查询剖析,如实行韶光、是否利用了索引、利用的是何种索引等信息都可以显示。
示例1(查询操持):利用uname条件进行检索剖析,可以看到"stage" :"IXSCAN",即利用了索引扫描。
示例2(实行状态剖析):在示例1的根本上,增加executionStats参数,会增加实行状态信息。
下面是对查询剖析中的几个关键参数的阐明。
(1)explain最为直不雅观的返回值是executionTimeMillis,指的是这条语句的实行韶光,这个值希望越小越好。
(2)nReturned为返回的条款、totalKeysExamined为索引扫描条款、totalDocsExamined为文档扫描条款,文档扫描数量当然也是越小越好,查询的空想的状态是:nReturned=totalKeysExamined=totalDocsExamined。
(3)stage状态剖析:查询中应只管即便利用索引,如FETCH+IDHACK、FETCH+IXSCAN 、 LIMIT+ ( FETCH +IXSCAN ) 、 PROJECTION+IXSCAN 、SHARDING_FITER+IXSCAN、COUNT_SCAN。只管即便不要涌现COLLSCAN,全表扫描严重影响查询性能,尤其是在MongoDB中数据量十分弘大时,合理利用索引进行查询,性能会有非常显著的提升。
COLLSCAN:全表扫描;IXSCAN:索引扫描;FETCH:根据索引去检索指定document;SHARD_MERGE:将各个分片返回数据进行merge;SORT:表明在内存中进行了排序;LIMIT:利用limit限定返回数;SKIP:利用skip进行跳过;IDHACK:针对_id进行查询;SHARDING_FILTER:通过MongoDB对分片数据进行查询;COUNT:利用db.coll.explain().count()之类进行count运算;
COUNTSCAN:count不该用Index进行count时的stage返回;COUNT_SCAN:count利用了Index进行count时的stage返回;SUBPLA:未利用索引的$or查询的stage返回;TEXT:利用全文索引进行查询时的stage返回;PROJECTION:限定返回字段时的stage返回。
十 案例:新浪微博MongoDB实战微博系统(如新浪微博),以用户发布博文为核心,然后会产生评论、点赞、关注、收藏、转发等干系操作(如图6-12所示)。
1 微博项目剖析
新浪微博用户数量弘大,如果采取传统的开拓模式,可以用关系数据库存储微博数据,微博系统表设计如图6-13所示。但是,由于关系数据库的Connection连接数量非常有限,而且CRUD(增编削查)操作受事务影响,因此当用户数量弘大时,性能会非常低。
图6-12 新浪微博
图6-13 微博系统表设计
如果采取MongoDB替代MySQL或Oracle,很多问题会迎刃而解。首先,MongoDB的数据库连接数单机可以达到几十万,远远超过MySQL的连接数;其次,MongoDB没有事务掌握,数据库读写性能大幅提升;再有,当用户数量弘大时,MongoDB集群非常随意马虎扩展,利用MongoDB集群的数据承载量远远大于MySQL数据库集群。
2 Java连接MongoDB
MongoDB的驱动下载,拜会github地址
http://MongoDB.github.io/MongoDB-Java-driver/(如图6-14所示)。
图6-14 MongoDB驱动下载
利用Maven下载MongoDB驱动,按如下进行配置(如图6-15所示)。
图6-15 MongoDB的驱动依赖
Java客户端利用驱动,获取MongoDB数据库连接的办法如下。
获取MongoDB数据库工具:
获取MongoDB凑集:
多个key/value组成的字符串,称为BSON工具:
获取文档工具:
3 微博项目代码实现
1.系统初始化脚本
微博系统的用户与博文数据作为初始化脚本写入,Java代码实现暂不考虑。
2.MongoDB访问封装
利用工具类MongoFactory管理MongoDB数据库的打开与关闭操作。
3.添加关注
“我的关注”是指登任命户对感兴趣的博主进行关注,关注人与被关注人都必须是系统的注册用户(如图6-13所示表设计),操作步骤如下。
(1)采取逻辑类UserBiz中addConcern()方法添加关注。
(2)持久层类UserDao中实现向MongoDB中添加关注信息。
(3)UI层添加关注。
4.我关注的职员列表
读取当前登任命户“我的关注”中的职员的信息列表,操作步骤如下。
(1)逻辑层UserBiz中getMyConcern()方法。
(2)持久层UserDao中getMyConcern()方法。
(3)UI层调用逻辑方法,显示“我的关注”的职员列表。
5.取消关注
从“我的关注”职员列表中移除某个人员,即为取消关注,操作步骤如下。
(1)逻辑层UserBiz中的removeConcern()方法。
(2)持久层UserDao中的removeConcern()方法。
(3)UI层调用逻辑方法,实现取消关注的功能。
6.添加博文收藏
登任命户在浏览博文时,可以对付感兴趣的博文进行收藏操作。从“我的收藏”中可以提取用户收藏的所有博文列表。
如图6-13所示的表设计,收藏博文表有两个外键,即用户名和博文id必须存在,才能成功进行博文收藏。收藏博文表是两个一对多的表示,即一个用户可以收藏多篇博文;一篇博文可以被多个用户同时收藏。
在MongoDB的用户凑集中写入内嵌文档,“我的收藏”作为用户凑集的内嵌文档进行存储(如图6-16所示)。
图6-16 内嵌文档存储“我的收藏”
(1)逻辑层UserBiz中collectWeibo()方法。博文收藏成功给博文的收藏数量加1。
(2)持久层UserDao中collectWeibo()方法。向用户凑集的内嵌文档写入数据,如果找不到用户名文档,则写入失落败。
(3)持久层WeiboDao中incCollectNum()方法。修正博文的收藏数量加1。
(4)UI层调用逻辑类,实现博文收藏。
7.取消博文收藏
(1)逻辑层UserBiz的collectWeiboCancel()方法。
(2)持久层UserDao中的collectWeiboCancel()方法。修正内嵌文档,移除指定条件的一条收藏数据。
(3)持久层WeiboDao中给博文收藏数量减1。
(4)UI层调用逻辑工具,实现取消收藏(如图6-17所示)。
图6-17 取消收藏