mongoDB
- MongoDB的引言
MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。 Nosql 技术门类 redis 内存型 mongodb 文档型
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
- MongoDB的特点
- 面向集合存储,易存储对象类型的数据
- 支持查询,以及动态查询
- 支持RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言
- 文件存储格式为BSON(一种JSON的扩展)
- 支持复制和故障恢复和分片
- MongoDB的安装和使用
- 下载mongoDB的安装包(最新版本3.6,只能在64位系统安装)这里使用的3.0.6版本
- 上传至linux系统中解压当前的linux系统
四、MongoDB的shell(客户端)操作
-
- 向集合中插入数据
db.集合名称.insert({name:'xiaohei',age:23,sex:true});
-
- 向集合中插入多条数据
db.集合名称.insert([{name:'xiaohei',age:23,sex:true},...]);
- Mongo中的删除数据
- db.集合名称.remove({条件}) //删除满足条件的数据
- db.集合名称.remove({不加任何条件})//删除所有文档 保留空的集合
- Mongo中的修改数据
- db.集合名称.update({条件},{更新内容});
- db.集合名称.update({"name":"zhangsan"},{name:"11",bir:new date()}) --这个更新是将符合条件的全部更新成后面的文档,相当于先删除在更新
- db.集合名称.update({"name":"xiaohei"},{$set:{name:"mingming"}}) --保留原来的值修改,但是只更新符合条件的第一条数据
- db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true}) ---保留原来数据更新,更新符合条件的所有数据
- db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true,upsert:true}) ---保留原来数据更新,更新符合条件的所有数据 没有条件符合时插入数据
- db.t_user.update({name:"zhangsan"},{$inc:{age:1}},{upsert:true,multi:true}) --在保留原始数据同时给符合条件的所有age这列的值自增指定的大小
- 删除集合
- db.集合名称.drop();
- 查询集合
- db.集合名称.find();
- db.集合名称.find({条件})
- db.集合名称.find({条件},{显示字段,name:1,age:1}) 1 显示 0 不显示 1和0 不能混合出现
- 查询结果排序:db.集合名称.find().sort({条件name:1,age:1}), 1 升序 -1 降序
- 分页查询:db.集合名称.find().sort({条件}).skip(起始条数).limit(显示总记录数);
- 总条数:db.集合名称.count();|db.t_user.find({"name":"aa"}).count();
- 模糊查询:使用正则表达式db.集合名称.find({"name":/go/})
- 等值(==)查询
db.user.find({name:"张三"});
db.user.find({name:{$eq:"张三"}});
-
- 且 ($and) 查询
db.t_user.find({name:"zhangsan",age:12});
db.t_user.find({$and:[{name:"zhangsan"},{id:10}]})
-
- $or使用:
- $or使用:
db.集合名称.find({
$or:[
{key:value},{age:{$gte:20}}
]
});
-
- $gt大于 $gte大于等于 $lt 小于 $lte 小于等于 $eq 等于:
- db.集合名称.find({“age”:{“$lte”:18,”$gte”:30}})
- $gt大于 $gte大于等于 $lt 小于 $lte 小于等于 $eq 等于:
-
- $nor查询使用
- db.t_user.find({$nor:[{name:"chenyn"},{age:26}]});
- $nor查询使用
- shell非正常关闭时,下次无法连接问题解决方案:
-
- 删除数据目录中的mongo.lock文件即可
-
五、Java操作mongoDB
- 项目中引入mongo的坐标
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.0.0</version>
</dependency>
- 使用java操作mongo
- 参见代码 mongo-java
六、Spring Boot整合mongoDB
- pom配置
pom包里面添加spring-boot-starter-data-mongodb包引用
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
- 在application.properties中添加配置
spring.data.mongodb.uri=mongodb://localhost:27017/test
- 详细操作参见springboot-mongo
- MongoDB中的索引
索引就是为了加速查询的,MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的优化技巧。下面是创建索引的命令:
- 创建索引:db.集合名称.ensureIndex({"name":1})
- 1 代表索引升序存储 -1 代表索引降序存储
- _id 默认自动创建索引
- 创建索引指定索引名称:db.集合名称.ensureIndex({"name":1},{name:"name_index"})
- 查看索引是否创建成功:db.集合名称.getIndexes()
- 删除索引的命令:db.集合名称.dropIndex({"name":1});
- 创建复合索引:db.集合名称.ensureIndex({"name":1, "age":-1,bir:1})
- 注意:
- 该索引被创建后,基于name和age的查询将会用到该索引
- 或者是基于name的查询也会用到该索引
- 但是只是基于age的查询将不会用到该复合索引。
- 总结:
- 如果想用到复合索引,必须在查询条件中包含复合索引中的前N个索引列。然而如果查询条件中的键值顺序和复合索引中的创建顺序不一致的话,MongoDB可以智能的帮助我们调整该顺序,以便使复合索引可以为查询所用。
- 注意:
-
-
- 如:db.t_user.find({"age": 30, "name": "stephen"})
对于上面示例中的查询条件,MongoDB在检索之前将会动态的调整查询条件文档的顺序,以使该查询可以用到刚刚创建的复合索引。
- 如:db.t_user.find({"age": 30, "name": "stephen"})
-
- 创建唯一索引:db.t_user.ensureIndex({"name":1},{"unique":true})
注意: 在缺省情况下创建的索引均不是唯一索引。一旦创建唯一索引, 如果再次插入name重复的文档时,MongoDB将报错,以提示插入重复键 (exception: E11000 duplicate key error index: zpark.t_user.$name_1 dup key: { : \"xiaohei\" })
- 重建索引:db.集合名称.reIndex();
- mongoDB中的主从复制(4.0版本废弃)
主从复制是mongoDB最常用的复制方式,这种方式非常灵活,可用于备份,故障恢复和扩展等.
- 搭建主从复制
- 准备三个机器一个主机两个备机
mongod --port 27017 --dbpath /root/data/master/ --bind_ip 0.0.0.0 --master --oplogSize 50
mongod --port 27018 --dbpath /root/data/slave1 --bind_ip 0.0.0.0 --slave --source 172.16.19.137:27017 --only baizhi –autoresync
mongod --dbpath /root/data/slave2 --port 27019 --bind_ip 0.0.0.0 --slave --source 172.16.19.137:27017 --only baizhi --autoresync --slavedelay 30
- 主从复制的选项
--master 主节点
--slave 从节点
--source arg 为从节点时从哪个主节点复制<server:port>
--only arg 为从节点时只复制主节点的那个库
--slavedelay arg 从节点延迟多长时间复制主节点 秒
--autoresync 从机数据不是最新是自动重新同步数据
--oplogSize 主节点的操作日志单位是M
- 查看集群状态:
rs.help();
rs.slaveOk(); //开启从机查询
- MongoDB中的副本集
MongoDB 副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组成。主从集群和副本集之间最明显的区别就是副本集没有固定的”主节点”,
整个集群会选举一个主节点,当主节点不能工作时自动变更到其他节点.
- 配置主机名
- vi /etc/hosts文件加入如下配置
- 当前主机地址 mongo
- vi /etc/hosts文件加入如下配置
- 搭建副本集
- 准备三个存放数据的目录并启动三个节点
mongod --port 27017 --dbpath /root/repl1 --bind_ip 0.0.0.0 --replSet myreplace/mongo:27018
mongod --port 27018 --dbpath /root/repl2 --bind_ip 0.0.0.0 --replSet myreplace/mongo:27019
mongod --port 27019 --dbpath /root/repl3 --bind_ip 0.0.0.0 --replSet myreplace/mongo:27017
注意: --replSet 副本集 myreplace 副本集名称/集群中其他节点的主机和端口
-
- 连接任意一台mongo
- use admin
- 执行如下命令
- 连接任意一台mongo
var config = {
_id:"myreplace",
members:[
{_id:0,host:"mongo:27017"},
{_id:1,host:"mongo:27018"},
{_id:2,host:"mongo:27019"}]
}
rs.initiate(config);//初始化配置
-
- 设置客户端临时访问数据:rs.slaveOk();
Springboot 操作副本集
spring.data.mongodb.uri=mongodb://127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019/ems(库名)?replcaSet=spock(副本集名称)
- Mongodb中的分片
- 分片(sharding)
分片目的是通过分片能够增加更多机器来应对不断的增加负载和数据,还不影响应用.
分片(sharding)是指将数据拆分,将其分散存在不同机器的过程,有时也用分区(partitioning)来表示这个概念,将数据分散在不同的机器上,不需要功能强大的大型计算机就能存储更多的数据,处理更大的负载.
MongoDB支持自动分片,可以摆脱手动分片的管理困扰,集群自动切分数据做负载均衡.MongoDB分片的基本思想就是将集合拆分成多个块,这些快分散在若干个片里,每个片只负责总数据的一部分,应用程序不必知道哪些片对应哪些数据,甚至不需要知道数据拆分了,所以在分片之前会运行一个路由进程,mongos进程,这个路由器知道所有的数据存放位置,应用只需要直接与mongos交互即可,mongos自动将请求转到相应的片上获取数据.从应用角度看分不分片没有什么区别.
- 什么时候分片
- 机器磁盘不够用了
- 单个的mongo已经不能满足写数据的性能需要了
- mongoDB的分片架构图
- 片键
设置分片时需要在集合中选一个键,用该键的值作为拆分数据的依据,这个片键称之为(shard key)
注意: 在真正的生产环境中,片键的选取很重要,片键的选取要一定要数据散列均匀
- 搭建分片集群
- 分片结构的端口如下
Shard Server 1:27020
Shard Server 2:27021
Shard Server 3:27022
Shard Server 4:27023
Config Server :27100
Config Server :27101
Config Server :27102
Route Process:40000
-
- 创建数据目录
mkdir -p /root/shard/s0
mkdir -p /root/shard/s1
mkdir -p /root/shard/s2
mkdir -p /root/shard/s3
mkdir -p /root/shard/config1
mkdir -p /root/shard/config2
mkdir -p /root/shard/config3
-
- 创建数据目录并启动四台shard机器
mongod --port 27020 --dbpath /root/shard/s0 --bind_ip 0.0.0.0 --shardsvr
mongod --port 27021 --dbpath /root/shard/s1 --bind_ip 0.0.0.0 --shardsvr
mongod --port 27022 --dbpath /root/shard/s2 --bind_ip 0.0.0.0 --shardsvr
mongod --port 27023 --dbpath /root/shard/s3 --bind_ip 0.0.0.0 --shardsvr
-
- 创建config数据目录启动配置机器
mongod --port 27100 --dbpath /root/shard/config1 --bind_ip 0.0.0.0 --replSet config/mongo:27101 --configsvr
mongod --port 27101 --dbpath /root/shard/config2 --bind_ip 0.0.0.0 --replSet config/mongo:27102 --configsvr
mongod --port 27102 --dbpath /root/shard/config3 --bind_ip 0.0.0.0 --replSet config/mongo:27100 --configsvr
-
- 初始化config的配置服务器副本集
- 登录任意config的server节点中使用 use admin
- config在admin中执行
- 初始化config的配置服务器副本集
var config = {
_id:"config",
configsvr: true,
members:[
{_id:0,host:"mongo:27100"},
{_id:1,host:"mongo:27101"},
{_id:2,host:"mongo:27102"}]
}
-
-
- 初始化副本集配置 rs.initiate(config);
-
-
- 启动路由
- mongos --port 40000 --configdb config/mongo:27100,mongo:27101,mongo:27102 --bind_ip 0.0.0.0
- 启动路由
注意: config为上面的副本集名称
-
- 客户端登陆到mongos中 mongo –port 40000
- use admin
- 添加分片节点:
- 客户端登陆到mongos中 mongo –port 40000
db.runCommand({ addshard:"mongo:27020","allowLocal":true });
db.runCommand({ addshard:"mongo:27021","allowLocal":true });
db.runCommand({ addshard:"mongo:27022","allowLocal":true });
db.runCommand({ addshard:"mongo:27023","allowLocal":true });
-
- 设置分片的库:db.runCommand({ enablesharding:"baizhi" });
- 设置那个库中那个集合以及片键信息:
db.runCommand({ shardcollection: "baizhi.users", key: { _id:1}})
db.runCommand({ shardcollection: "baizhi.users", key: { _id: "hashed"}})