- MongoDB特点
1.支持特别查询
- 在MongoDB中,可以通过字段,范围查询进行搜索,并且还支持正则表达式搜索。
2.索引
- 可以索引文档中的任何字段。
3.复制
- MongoDB支持主从复制。主机可以执行读写操作,从机从主机复制数据,只能用于读取或备份(不写入)
4.复制数据
- MongoDB可以在多台服务器上运行。 复制数据以保持系统正常运行,并在硬件故障的情况下保持其运行状态。
5.负载均衡
- 由于数据放在碎片中,因此具有自动负载平衡配置。
6.支持映射缩减和聚合工具
7.使用JavaScript而不是Procedure
8.它是一个用C++编写的无模式数据库
9.提供高性能
10.轻松存储任何大小的文件,而不会使您的堆栈复杂化
11.在故障的情况下易于管理
12.它还支持:
- 具有动态模式的JSON数据模型
- 自动分片用于水平可扩展性
- 内置复制高可用性
二、安装配置
1.下载安装
在Windows上安装 MongoDB,首先打开: http://www.mongodb.org/downloads 下载最新版本的
2.MongoDB配置(mongodb.conf)
#数据库路径
dbpath=C:\Program Files\MongoDB\Server\3.4\data
#日志输出文件路径
logpath=C:\Program Files\MongoDB\Server\3.4\logs\mongo.log
#错误日志采用追加模式
logappend=true
#启用日志文件,默认启用
journal=true
#这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为false
quiet=true
#端口号 默认为27017
port=27017
3.Windows服务配置(mongodb.bat)
--启动MongoDB服务
mongod --config "C:\Program Files\MongoDB\Server\3.4\mongo.conf"
--添加启动服务
mongod --config "C:\Program Files\MongoDB\Server\3.4\mongo.conf" --install --serviceName "MongoDB"
--添加带权限认证的
mongod --config "C:\Program Files\MongoDB\Server\3.4\mongo.conf" --auth --install --serviceName "MongoDB"
--启动服务
net start MongoDB
--删除服务
mongod.exe --remove --serviceName "MongoDB"
sc delete MongoDB
--
4.用户权限配置(启动后执行mongo.exe)命令
use admin
--创建用户
db.createUser({user:"admin",pwd:"admin",roles:["userAdminAnyDatabase","dbAdminAnyDatabase","root"]})
--创建角色
db.createRole({
"role": "mongostatRole",
"privileges": [
{
"resource": {
"cluster": true
},
"actions": [
"serverStatus"
]
}
],
"roles": []
})
--授权用户角色
db.grantRolesToUser("admin",[{role: "mongostatRole",db: "admin"}])
--创建其他用户
db.createUser({
"user": "dba",
"pwd": "dba",
"db" : "ucloudlink",
"roles": [
{
"role" : "readWrite",
"db" : "ucloudlink"
},
{
"role" : "readWrite",
"db" : "newdb"
}
]
})
三、MongoDB数据类型
MongoDB支持许多数据类型。 其中一些是 -
- 字符串 - 这是用于存储数据的最常用的数据类型。MongoDB中的字符串必须为UTF-8。
- 整型 - 此类型用于存储数值。 整数可以是32位或64位,具体取决于服务器。
- 布尔类型 - 此类型用于存储布尔值(true / false)值。
- 双精度浮点数 - 此类型用于存储浮点值。
- 最小/最大键 - 此类型用于将值与最小和最大BSON元素进行比较。
- 数组 - 此类型用于将数组或列表或多个值存储到一个键中。
- 时间戳 - ctimestamp,当文档被修改或添加时,可以方便地进行录制。
- 对象 - 此数据类型用于嵌入式文档。
- Null - 此类型用于存储Null值。
- 符号 - 该数据类型与字符串相同; 但是,通常保留用于使用特定符号类型的语言。
- 日期 - 此数据类型用于以UNIX时间格式存储当前日期或时间。您可以通过创建日期对象并将日,月,年的日期进行指定自己需要的日期时间。
- 对象ID - 此数据类型用于存储文档的ID。
- 二进制数据 - 此数据类型用于存储二进制数据。
- 代码 - 此数据类型用于将JavaScript代码存储到文档中。
- 正则表达式 - 此数据类型用于存储正则表达式。
四、使用MongoDB数据库
1、登录数据库
Mongo
User admin
db.auth(“admin”,”admin”);
show dbs
--带认证的登录
mongo --port 27017 -u "admin" -p "admin" --authenticationDatabase "admin"
2、创建数据库
user newdb
3、删除数据库
db.dropDatabase()
4、创建集合
MongoDB 的 db.createCollection(name,options) 方法用于在MongoDB 中创建集合。
语法
createCollection()命令的基本语法如下 -
db.createCollection(name, options)
在命令中,name 是要创建的集合的名称。 options是一个文档,用于指定集合的配置。
参数 | 类型 | 描述 |
name | String | 要创建的集合的名称 |
options | Document | (可选)指定有关内存大小和索引的选项 |
options参数是可选的,因此只需要指定集合的名称。 以下是可以使用的选项列表:
字段 | 类型 | 描述 |
capped | Boolean | (可选)如果为true,则启用封闭的集合。上限集合是固定大小的集合,它在达到其最大大小时自动覆盖其最旧的条目。 如果指定true,则还需要指定size参数。 |
autoIndexId | Boolean | (可选)如果为true,则在_id字段上自动创建索引。默认值为false。 |
size | 数字 | (可选)指定上限集合的最大大小(以字节为单位)。 如果capped为true,那么还需要指定此字段的值。 |
max | 数字 | (可选)指定上限集合中允许的最大文档数。 |
在插入文档时,MongoDB首先检查上限集合capped字段的大小,然后检查max字段。
5、删除集合
MongoDB 的 db.collection.drop()
用于从数据库中删除集合。
6、聚合
6.1、count() 方法
db.article.count();
db.article.count({by_user:"Maxsu"})
6.2、distinct()方法
db.article.distinct('by_user')
db.runCommand({"distinct":"article","key":"by_user"})
6.3、aggregate()方法
db.article.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
6.4、group()方法
7、索引
索引支持查询的有效地提高效率。没有索引,MongoDB必须扫描集合的每个文档,以选择与查询语句匹配的文档。这种扫描效率很低,需要 MongoDB 处理大量的数据。
索引是特殊的数据结构,以易于遍历的形式存储数据集的一小部分。 索引存储特定字段或一组字段的值,按照索引中指定的字段值排序。
要创建索引,需要使用MongoDB的ensureIndex()
方法。
语法
ensureIndex()
方法的基本语法如下 -
>db.COLLECTION_NAME.ensureIndex({KEY:1})
这里的key
是要在其上创建索引的字段的名称,1
是升序。 要按降序创建索引,需要使用-1
。
示例
>db.mycol.ensureIndex({"title":1})
Shell
在ensureIndex()
方法中,可以传递多个字段,以在多个字段上创建索引。
>db.mycol.ensureIndex({"title":1,"description":-1})
ensureIndex()
方法也接受选项列表(可选)。 以下是列表 -
参数 | 类型 | 描述 |
|
| 在后台构建索引,以便构建索引不会阻止其他数据库活动,则指定 |
|
| 创建一个唯一的索引,使得集合不会接受索引键或键匹配索引中现有值的文档的插入。 指定 |
|
| 索引的名称。如果未指定,则MongoDB通过连接索引字段的名称和排序顺序来生成索引名称。 |
|
| 在可能有重复项的字段上创建唯一索引。MongoDB仅索引第一次出现的键,并从集合中删除包含该键的后续出现的所有文档。指定 |
|
| 如果为 |
|
| 指定一个值(以秒为单位)作为 |
| 索引版本 | 索引版本号。默认索引版本取决于创建索引时运行的MongoDB的版本。 |
| 文档 | 权重是从 |
|
| 对于文本索引,确定停止词列表的语言以及句柄和分词器的规则。 默认值为英文。 |
|
| 对于文本索引,要指定文档中包含覆盖默认语言的字段名称。默认值为 |
五、MongoDB 监控
1、连接MongoDB
mongo --port 27017 -u "admin" -p "admin" --authenticationDatabase "admin"
2、mongostat
此命令检查所有运行的mongod实例的状态,并返回数据库操作的计数器。 这些计数器包括插入,查询,更新,删除和游标。 命令还显示遇到页面错误,并显示锁定百分比。这可以用来监控内存不足,写入容量或出现性能问题。
Mongostat 5 --port 27017 -u "admin" -p "admin" --authenticationDatabase "admin"
3、mongotop
此命令跟踪并报告基于集合的 MongoDB 实例的读写活动。 默认情况下,mongotop会在每秒钟内返回信息,但是可相应地更改信息。应该检查此读写活动是否符合您的应用意图,并且要一次对数据库发出太多的写入操作,从磁盘读取的频率太高,或者超出了工作集合大小。
mongotop 5 --port 27017 -u "admin" -p "admin" --authenticationDatabase "admin"
六、MongoDB关联关系
MongoDB中的关系表示各个文档在逻辑上的相互关联。关系可以通过嵌入式和引用方法建模。 这种关系可以是1
:
1
,1
:
N
,N
:
1
或N
:
N
。
假设有一种情况:要存储用户的地址。一个用户可以拥有多个地址,这就是1
:
N
关系。
以下是用户(users
)文档示例的文档结构 -
{
"_id":10999110,
"name": "Maxsu",
"contact": "13888990021",
"dob": "1992-10-11"
}
以下是地址(address
)文档的示例文档结构 -
{
"_id":12200,
"building": "Hainan Building NO.2100",
"pincode": 571100,
"city": "Haikou",
"province": "Hainan"
}
1、嵌入式关系建模
在嵌入式方法中,我们将地址(address
)文档嵌入到用户(users
)文档中。
{
"_id": 21000100,
"contact": "13800138000",
"dob": "1991-11-11",
"name": "Maxsu",
"address": [
{
"building": "Hainan Building NO.2100",
"pincode": 571100,
"city": "Haikou",
"province": "Hainan"
},
{
"building": "Sanya Building NO.2100",
"pincode": 572200,
"city": "Sanya",
"province": "Hainan"
},
]
}
该方法将所有相关数据保存在单个文档中,这使得检索和维护更容易。可以使用单个查询来在整个文档检索,例如 -
> db.users.findOne({"name":"Maxsu"},{"address":1, "name":1})
请注意,缺点是如果嵌入式文档的大小如果不断增长,可能会影响读/写性能。
2、建模参考关系
这是设计规范化关系的方法。 在这种方法中,用户和地址文件将分别维护,但用户文档将包含一个将引用地址文档的id
字段的字段。
{
"_id":ObjectId("52ffc33321332111sdfaf"),
"contact": "13800138000",
"dob": "1991-11-11",
"name": "Maxsu",
"address_ids": [
ObjectId("123123"),
ObjectId("123412")
]
}
如上所示,用户文档包含对应地址的ObjectId
的数组字段address_ids
。 使用这些ObjectIds,我们可以从那里查询地址文件并获取地址详细信息。 使用这种方法,需要两个查询:首先从用户文档获取address_ids
字段,然后从地址集中获取这些地址。
>var result = db.users.findOne({"name":"Maxsu"},{"address_ids":1})
>var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})
七、MongoDB数据库引用
DBRefs
考虑一个示例场景,在这个场景中将使用DBRefs而不是手动引用,设计有一个数据库中将不同类型的地址(家庭,办公室,邮件等)存储在不同的集合(address_home
,address_office
,address_mailing
等)中。 现在,当用户集合的文档引用地址时,还需要根据地址类型指定要查找的集合。 在这种情况下,文档引用了多个集合中的文档,则应该使用DBRefs。
使用DBRefs
DBRefs中有三个字段 -
$ref
- 此字段指定引用文档的集合$id
- 此字段指定引用文档的_id
字段$db
- 这是一个可选字段,并包含引用文档所在的数据库的名称
假设一个具有DBRef字段address
的示例用户文档,如代码片段所示 -
{
"_id":ObjectId("348362491fjaskdlf2314"),
"address": {
"$ref": "address_home",
"$id": ObjectId("sfaafdf4137832149fssa"),
"$db": "ucloudlink"},
"contact": "13800138000",
"dob": "1991-12-12",
"name": "Maxsu"
}
这里的 DBRef 字段 address
指定引用的地址文件位于ucloudlink数据库中的address_home
集合中,其ID为sfaafdf4137832149fssa
。
以下代码由$ref
参数(在示例中为address_home
)指定的集合中动态地查找ID为DBRef中的$id
参数指定的文档。
>var user = db.users.findOne({"name":"Maxsu"})
>var dbRef = user.address
>db[dbRef.$ref].findOne({"_id":(dbRef.$id)})
以上代码返回address_home
集合中存在的以下address
文档中
{
"_id" : ObjectId("sfaafdf4137832149fssa"),
"building" : "Hainan Apt No.2100",
"pincode" : 571100,
"city" : "Haikou",
"province" : "Hainan"
}
八、Java连接MongoDB操作
九、Mongodb集群搭建
Mongodb的三种集群方式的搭建:Replica Set / Sharding / Master-Slaver
1、Replica Set(副本集)
简单来说就是集群当中包含了多份数据,保证主节点挂掉了,备节点能继续提供数据服务,提供的前提就是数据需要和主节点一致。如下图:
Mongodb(M)表示主节点,Mongodb(S)表示备节点,Mongodb(A)表示仲裁节点。主备节点存储数据,仲裁节点不存储数据。客户端同时连接主节点与备节点,不连接仲裁节点。
默认设置下,主节点提供所有增删查改服务,备节点不提供任何服务。但是可以通过设置使备节点提供查询服务,这样就可以减少主节点的压力,当客户端进行数据查询时,请求自动转到备节点上。这个设置叫做Read Preference Modes,同时Java客户端提供了简单的配置方式,可以不必直接对数据库进行操作。
仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点。这里虽然只有一个备节点,但是仍然需要一个仲裁节点来提升备节点级别。我开始也不相信必须要有仲裁节点,但是自己也试过没仲裁节点的话,主节点挂了备节点还是备节点,所以咱们还是需要它的。
接下来Windows环境创建一个Replica Set(副本集):
-
- 建立配置文件
C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs0.conf
C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs1.conf
C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs2.conf
1.2、创建复制集服务
sc.exe create OpenXLive.MongoDB_Ad.Shard_a0 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs0.conf\"" DisplayName= "rs_a0_Service" start= "auto"
sc.exe create OpenXLive.MongoDB_Ad.Shard_a1 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs1.conf\"" DisplayName= "rs_a1_Service" start= "auto"
sc.exe create OpenXLive.MongoDB_Ad.Shard_a2 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\a\rs2.conf\"" DisplayName= "rs_a2_Service" start= "auto"
1.3、配置及初始化 Replica Sets
初始化配置,使上面的配置生效
call mongo.exe 127.0.0.1:10000/admin
--一个简单的复制集最少包括三个节点。 1.primary 2. secondary,3.arbiter节点
cfg={_id: 'rs_a', members:[{_id:0,host:'127.0.0.1:10000',priority:2}, {_id:1,host:'127.0.0.1:10001',priority:1},{_id:2,host:'127.0.0.1:10002',arbiterOnly:true}]};
rs.initiate(cfg);
查看复制集状态
rs.conf();
rs.status();
在primary节点上查看复制集状态:
rs.isMaster()
`2、分片集群架构
分片集群主要有mongos路由进程、配置服务器、复制集组成的分片集合组成。 如下图:
- 碎片(Shards) - 碎片用于存储数据。它们提供高可用性和数据一致性。 在生产环境中,每个分片是一个单独的副本集。
- 配置服务器(Config Servers) - 配置服务器存储集群的元数据。 该数据包含集群的数据集与分片的映射。查询路由器使用此元数据将操作定位到特定的分片。 在生产环境中,分片集群正好有
3
个配置服务器。 - 查询路由器(Query Routers) - 查询路由器基本上是 mongo 实例,与客户端应用程序的接口和直接操作到适当的分片。 查询路由器处理并将操作定向到碎片,然后将结果返回给客户端。 分片集群可以包含多个查询路由器来分割客户端请求负载。 客户端向一个查询路由器发送请求。 一般来说,分片集群有许多查询路由器。
分片集群上一个分片(shard) 就是一个复制集。 当然也可以是一个单个Mongod实例。在集群中一般用复制集。保证一个分片不会故障。如果一个分片出现故障。整个集群就挂了。因为每一个分片上保留数据的一部分。所有分片的综合才是所有数据。所以我们应该保证每个分片上数据的完整性和稳定性至关重要。
Mongos和配置服务器是轻量级进程。是不会保存数据的。 配置服务器只保存分片的一些状态信息。 所以整个读取集群的过程为: 访问Mongos-查询配置服务器,根据配置服务器要求写入或读取那些分片服务器进行读取数据。
2.1、创建副本集
创建副本集b、c
2.2、创建配置服务
sc.exe create OpenXLive.MongoDB_Ad.Shard_cfg0 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\configsvr\cfgserver_0.conf"" DisplayName= "rs_cfg0_Service" start= "auto"
sc.exe create OpenXLive.MongoDB_Ad.Shard_cfg1 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\configsvr\cfgserver_1.conf"" DisplayName= "rs_cfg1_Service" start= "auto"
sc.exe create OpenXLive.MongoDB_Ad.Shard_cfg2 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\configsvr\cfgserver_2.conf"" DisplayName= "rs_cfg2_Service" start= "auto"
call mongo.exe 127.0.0.1:40000/admin
cfg={_id: 'configs', members:[{_id:0,host:'127.0.0.1:40000'}, {_id:1,host:'127.0.0.1:40001'},{_id:2,host:'127.0.0.1:40002'}]};
rs.initiate(cfg);
2.3、创建路由服务
sc.exe create rs_mongosr_Service1 binPath= "\"C:\Program Files\MongoDB\Server\3.4\bin\mongos.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.4\cluster\config\mongos\cfg_mongos.conf"" DisplayName= "rs_mongosr_Service1" start= "auto"
直接启动
mongos --config "C:\Program Files\MongoDB\Server\3.4\cluster\config\mongos\cfg_mongos.conf"
call mongo.exe 127.0.0.1:50000/admin
db.runCommand({addshard:"rs_a/127.0.0.1:10000,127.0.0.1:10001",name:"ShardSetA"})
db.runCommand({addshard:"rs_b/127.0.0.1:20000,127.0.0.1:20001",name:"ShardSetB"})
db.runCommand({listshards : 1})
printShardingStatus()
db.runCommand({"enablesharding":"ucloudlink"})
sh.status()
十、MongoDB其他高级特性
1、MongoDB原子操作
2、MongoDB高级索引
3、MongoDB Map Reduce
根据MongoDB文档的说明,Map-reduce是将大量数据合并为有用的聚合结果的数据处理范例。 MongoDB使用mapReduce
命令进行map-reduce
操作。MapReduce通常用于处理大型数据集。
以下是基本 mapReduce
命令的语法 -
>db.collection.mapReduce(
function() {emit(key,value);}, //map function
function(key,values) {return reduceFunction}, { //reduce function
out: collection,
query: document,
sort: document,
limit: number
}
)
map-reduce
函数首先查询集合,然后将结果文档映射到发出的键值对,然后根据具有多个值的键进行减少。
在上面的语法 -
map
是一个JavaScript函数,它将一个值与一个键映射并发出一个键值对;reduce
是一个javascript功能,可以减少或分组具有相同键的所有文档;out
指定map-reduce
查询结果的位置;query
指定选择文档的可选选择条件;sort
指定可选的排序条件;limit
指定可选的最大文档数;
请考虑存储用户帖子的以下文档结构。 该文档存储用户的user_name
和帖子的状态(status
)。
{
"post_text": "bilin tutorials is an awesome website for tutorials",
"user_name": "maxsu",
"status":"active"
}
现在,我们将在posts
集上使用mapReduce
函数来选择所有status
的值为active
的帖子,并根据user_name
分组,然后使用以下代码对每个用户的帖子数进行计数
>db.posts.mapReduce(
function() { emit(this.user_id,1); },
function(key, values) {return Array.sum(values)}, {
query:{status:"active"},
out:"post_total"
}
)
4、MongoDB文本搜索
5. MongoDB正则表达式
正则表达式在所有的编程语言中经常使用,用于以搜索任何字符串中的模式或单词。 MongoDB还提供使用$regex
运算符的字符串模式匹配的正则表达式的功能。 MongoDB使用PCRE(Perl兼容正则表达式)作为正则表达式语言。
与文本搜索不同,不需要使用任何配置或命令来使用正则表达式。
请考虑以下文档结构,其中包含post
文本及其标签 -
{
"post_text": "enjoy the mongodb articles on bilin tutorials",
"tags": [
"mongodb",
"bilin"
]
}
以下regex
查询搜索包含”bilin
“字符串的所有帖子 -
>db.posts.find({post_text:{$regex:"bilin"}})
上面的查询也可以写成 -
>db.posts.find({post_text:/bilin/})
要使搜索不区分大小写,可指定$options
参数的值为$i
。 以下命令将寻找具有单词bilin
的字符串,不管其是小写还是大写字母 -
>db.posts.find({post_text:{$regex:"bilin", $options:"$i"}})
此查询返回的结果之一是以下文档,其中包含大小写字母的”bilin
“单词 -
{
"_id" : ObjectId("595b99e1f6a6243715b3c316"),
"post_text" : "hey! this is my post on Bilin Bilin",
"tags" : [ "bilin" ]
},
{
"_id" : ObjectId("595b99e1f6a6243715b3c317"),
"post_text" : "hey! this is my post on bilin Bilin",
"tags" : [ "bilin" ]
}
我们也可以在数组字段上使用正则表达式。当实现标签的功能时,这尤其重要。 所以,如果要从单词:tutorial
(tutorial
,tutorials
, tutorialpoint
或 tutorialphp
或 tutorialpython
或 tutorialphp
)开始搜索所有具有标签的帖子,可以使用以下代码 -
> db.posts.find({tags:{$regex:"tutorial"}})
- 如果文档字段创建了索引,则查询将使用索引值来匹配正则表达式。 与正常表达式扫描整个集合相比,使用索引值使得搜索非常快。
- 如果正则表达式是前缀表达式,则所有匹配都是以某个字符串字符开始。 例如,如果正则表达式是
^tut
,则查询必须仅搜索以tut
开头的那些字符串。
6、MongoDB自动递增序列