MongoDB的应用场景
mondoDB是一个分布式的文件存储数据库, 同时他也是一个NoSql数据库, 主要是为WEB应用提供可扩展的高性能解决方案, MongoDB是一个内存型数据库, 因此会存在数据丢失的问题, 所以应用时不能将严格的保证不丢失的数据放到MongoDB中, 最为最终的存储解决方法;
- 网站实时数据: 日志, 用户行为, 时间轴
- 数据缓存: 缓存的数据是临时的, 要在关系型数据库中保存
- 大尺寸低价值数据: 图片文件或者视频文件
- 高伸缩性场景: 机器任意增加或减少的场景
- 对象或者JSON存储
不适用范围
- 高度事务性系统: 金融系统
- 高机密的用户数据
- 结构化关联查询要求非常高的: 如报表系统
MongoDB术语
mysql | mongoDB | 解释 |
---|---|---|
DataBase | DataBase | 数据库 |
table | collection | 表或集合 |
Row | Dcoument | 数据行 |
Colum | Field | 数据列,字段 |
index | index | 索引 |
Table join | 不支持 | 表关联 |
PremaryKey | ObjectID | 主键 |
数据类型
数据类型 | 说明 | 举例 |
---|---|---|
Null | null值 | {x: null} |
Boolean | 布尔值 | {x: true} |
Integer | 整数 | {x: 1} |
Double | 浮点数 | {x: 3.14} |
String | 字符串 | {x: "字符串"} |
ObjectID | 对象ID | {x: ObjectID()} |
Date | 时间 | {x: new Date()} |
TimeStamp | 时间戳 | {x: 142343214123} |
Array | 数组 | {x: ["a","b"]} |
Object | 内嵌文档 | {x: {"a","b"}} |
单机MongoDB的安装和启动
- 官网下载tar包并解压
- 创建data数据目录, 和logs日志目录
- 创建配置文件mono.conf, 内容如下:
- 配置环境变量: vi /etc/profile, 最后一行添加export PATH=$PATH:/mongodb/mongodb-linux-x86_64-debian92-4.0.3/bin, 然后执行source /etc/profile
- 使用./bin/mongod -f ./mongo.conf启动
- 执行./mongo看是否能进入程序
mongo.conf内容
dbpath=/mongodb/data
logpath=/mongodb/logs/mongo.log
logappend=true
journal=true
quiet=true
port=27017
fork=true #后台运行
bind_ip=0.0.0.0 #允许任何IP进行连接
auth=false #是否授权连接
连接使用工具
Robo3T
MongoDB架构
写数据过程
读数据过程
mongos是mongod的协调中心, 客户端和服务端交互的通道;
mongod Config是配置中心
mongod是数据库
spring-boot整合MongoDB
- 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
- yml文件中添加相关配置
spring.data.mongodb.uri=mongodb://192.168.1.11:27017/testdb
- 注入MongoTemplate使用即可
mongoDB语法
x #查询年龄大于等于 25 小于等于 27 的人
db.t_member.find({age:{$gte:25,$lte:27}},{_id:0,name:1,age:1})
#查询出所有国籍不是韩国的人的数学成绩
db.t_member.find({country:{$ne:"韩国"}},{_id:0,name:1,country:1})
$in 或 $nin
#查询国籍是中国或美国的学生信息
db.t_member.find({country:{$in:["China","USA"]}},{_id:0,name:1:country:1})
#查询语文成绩大于 85 或者英语大于 90 的学生信息
db.t_member.find({$or:[{c:{$gt:85}},{e:{$gt:90}}]},{_id:0,name:1,c:1,e:1})
#把中国国籍的学生上增加新的键 sex
db.t_member.update({country:"China"},{$set:{sex:"m"}},false,true)
#查询出 sex 为 null 的人
db.t_member.find({sex:{$in:[null]}},{_id:0,name:1,sex:1})
#查询出名字中存在”li”的学生的信息
db.t_member.find({name:/li/i},{_id:0,name:1})
$not 和$nin 的区别是$not 可以用在任何地方儿$nin 是用到集合上的
#查询出名字中不存在”li”的学生的信息
db.t_member.find({name:{$not:/li/i}},{_id:0,name:1})
#查询喜欢看 MONGOD 和 JS 的学生
db.t_member.find({books:{$all:["JS","MONGODB"]}},{_id:0,name:1})
#查询第二本书是 JAVA 的学习信息
db.t_member.find({"books.1":"JAVA"},{_id:0,name:1,books:1})
#查询出喜欢的书籍数量是 4 本的学生
db.t_member.find({books:{$size:4}},{_id:0,name:1})
查询出喜欢的书籍数量大于 4 本的学生本的学生
增加 size 键
db.t_member.update({},{$set:{size:4}},false,true)
添加书籍,同时更新 size
db.t_member.update({name:"jim"},{$push:{books:"ORACL"},$inc:{size:1}
})
查询大于 3 本的
db.t_member.find({size:{$gt:4}},{_id:0,name:1,size:1})
#查询出 Jim 书架中第 2~4 本书
db.t_member.find({name:"jim"},{_id:0,name:1,books:{$slice:[1,3]}})
#查询出最后一本书
db.t_member.find({name:"jim"},{_id:0,name:1,books:{$slice:-1}})
查询出在 K 上过学且成绩为 A 的学生
绝对查询,顺序和键个数要完全符合
db.t_member.find({school:{school:"K","score":"A"}},{_id:0,name:1})
对象方式,但是会出错,多个条件可能会去多个对象查询
db.t_member.find({"school.school":"K","school.score":"A"},{_id:0,name:1})
正确做法单条条件组查询$elemMatch
db.t_member.find({school:{$elemMatch:{school:"K",score:"A"}},{_id:0,name:1})
db.t_member.find({age:{$gt:22},books:"C++",school:"K"},{_id:0,name:1,age:1,books:1,school:1})
分页与排序
1)limit 返回指定条数 查询出 persons 文档中前 5 条数据:
db.t_member.find({},{_id:0,name:1}).limit(5)
2)指定数据跨度 查询出 persons 文档中第 3 条数据后的 5 条数据
db.t_member.find({},{_id:0,name:1}).limit(5).skip(3)
3)sort 排序 1 为正序,-1 为倒序
db.t_member.find({},{_id:0,name:1,age:1}).limit(5).skip(3).sort({age:1})
$inc :只使用于数字类型,可以为指定键值对的数字类型进行加减操作:
db.t_member.update({name:"zhangsan"},{$inc:{age:2}})
执行结果是名字叫“zhangsan”的年龄加了 2
$unset : 删除指定的键
db.t_member.update({name:"zhangsan"},{$unset:{age:1}})
$push : 数组键操作:1、如果存在指定的数组,则为其添加值;2、如果不存在指定的数组,则
创建数组键,并添加值;3、如果指定的键不为数组类型,则报错;
$addToSet : 当指定的数组中有这个值时,不插入,反之插入
#则不会添加到数组里
db.t_member.update({name:"zhangsan"},{$addToSet:{classes:"English"}});
$pop:删除指定数组的值,当 value=1 删除最后一个值,当 value=-1 删除第一个值
#删除了最后一个值
db.t_member.update({name:"zhangsan"},{$pop:{classes:1}})
$pull : 删除指定数组指定的值
#$pullAll 批量删除指定数组
db.persons.update({name:"zhangsan"},{$pull:{classes:"Chinese"}})
#若数组中有多个 Chinese,则全删除
db.t_member.update({name:"zhangsan"},{$pull:{classes:["Chinese"]}})
$ : 修改指定数组时,若数组有多个对象,但只想修改其中一些,则需要定位器:
db.t_member.update({"classes.type":"AA"},{$set:{"classes.$.sex":"male"}})
$addToSet 与 $each 结合完成批量数组更新操作
db.t_member.update({name:"zhangsan"},{$set:{classes:{$each:["chinese","art"]}}})
MongoDB高可用
cluster 主从架构(M-A-S, A代表仲裁节点, 该节点不承担数据存储功能, 这台机器挂点也没问题, 主从中其中一台可以承担这个角色)
创建用户命令:
db.createUser({user:"admin",pwd:"123",roles:[{role:"dbAdmin",db:"testdb"}]})
db.auth("admin","123")
使用show roles查看所有的角色
config文件配置
除了上面的配置之外, 再添加如下字段:
#表示集群的名字
replSet=...
三台机器都是用相同的配置并启动;
随意登录一台机器进行集群初始化
#使用admin数据库
use admin
cfg={_id:"replSet02",members:[{_id:0,host:'ip1:27017',priority:9},{_id:1,host:'ip2:27017',priority:1},{_id:2,host:'ip3:27017',arbiterOnly:true}]};
#使配置生效
rs.initiate(cfg)
#查看状态
rs.status()
mongodb官方推荐模式(需要使用至少8台服务器)
- 配置文件中添加该配置shardsvr=true, 配置三台机器, 配置相同的集群名称, 启动, 然后使用上面的方法是配置生效;
- 配置文件中添加configsvr=true, 配置三台机器, 配置相同的集群名称, 注意不要和上面的相同, 启动, 和一种相同的操作;
- 配置路由节点添加如下配置:
configdb=configrs/ip1:28001,ip2:28001,ip3:20881
去掉dbpath和replSset配置, 启动:
./mongos -f /mongodb.cfg
- 连接路由节点进行配置:
mongo 192.168.209.128:30000
#这里必须连接路由节点
sh.addShard("shard001/192.168.209.128:27001");
sh.addShard("shard002/192.168.209.128:27017");
#shard001、shard002 表示 replica set 的名字 当把主节点添加到 shard 以后,会
自动找到 set 里的主,备,决策节点
use testdb
sh.enableSharding("testdb") #testdb is database name
sh.shardCollection("testdb.testcon",{"name":”hashed”})
db.collection.status()
整个架构和es架构的思想比较类似, 只有数据量真的较大时使用才会显示他的作用;
MongoDB索引
创建索引
db.books.ensureIndex{{number:1}}
创建索引同时指定索引的名字
db.books.ensureIndex({number:1},{name:"book_"})
索引使用需要注意的地方
- 创建索引的时候注意 1 是正序创建索引-1 是倒序创建索引
- 索引的创建在提高查询性能的同事会影响插入的性能 对于经常查询少插入的文档可以考虑用索引
- 符合索引要注意索引的先后顺序
- 每个键全建立索引不一定就能提高性能呢 索引不是万能的
- 在做排序工作的时候如果是超大数据量也可以考虑加上索引 用来提高排序的性能
唯一索引
#则插入相同的 name 值会报错
db.books.ensureIndex({name:-1},{unique:true})
#如果建议唯一索引之前已经有重复数值如何处理
#剔除重复数值
db.books.ensureIndex({name:1},{name:"book_",unique:true,dropDups:true})
其他操作
#强制查询已经建立好的索引
#后一个 name 为索引名,正序倒序依据建立索引的规则,否则会报错
db.books.find({name:"323book"}).hint({name:1})
#查询索引信息和查询状态信息
db.books.find({name:"123book"}).explain()
#批量和精确删除索引
db.runCommand({dropIndexes : "books" , index:"name_-1"})
db.runCommand({dropIndexes : "books" , index:"*"})
数据导入导出
把数据好 testdb 中的 persons 导出
mongoexport -d testdb -c persons -o D:/persons.json
导出其他主机数据库的文档
mongoexport --host 192.168.0.16 --port 37017
导入数据(中断其他操作)
mongoimport --db testdb --collections persons --file d:/persons.json
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。