文章目录
MongoDB(文档数据库)
介绍
-
MongoDB是为快速开发互联网Web应用而设计的数据库系统
-
MongoDB的设计目标是极简、灵活、作为Web应用栈的一部分
-
MongoDB的数据模型是面向文档的,所谓文档是一种类似于JSON的结构
安装
MongoDB的版本偶数版本为稳定版,奇数版本为开发版。
官网:https://www.mongodb.com/try/download/community
-
Linux中安装
# 1.下载 # 2.解压 tar -zxvf mongodb-linux-***.tgz # 3.将解压包移动到指定目录 mv mongodb-***/ /usr/local/mongodb # 4.创建数据存放目录与日志存放目录 mkdir -p /usr/local/mongodb/data /usr/local/mongodb/logs # 5.启动MongoDB服务 /usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data --logpath=/usr/local/mongodb/logs/mongodb.logs --logappend --port=27017 --fork # 后期登录 /usr/local/mongodb/bin/mongo
-
windows中安装 (略)
MongoDB基本操作
-
查看数据库
show databases
-
使用数据库
use 数据库名称
在mongodb中选择不存在的数据库不会报错,隐式创建(后期当该数据库中有数据时自动创建)
-
创建数据库
隐式创建
-
删除数据库
- 先使用数据库
- db.dropDatabase()
-
查看集合
show collections
-
创建集合
db.createCollection(‘集合名’)
-
删除集合
db.集合名.drop()
-
集合的导入与导出
# 导出 # ip+端口 数据库名 集合名 导出文件 mongoexport -h localhost:27017 -d tangmin -c student -o d:/c1.json # 导入 # ip+端口 数据库名 集合名 导入文件 mongoimport -h localhost:27017 -d local -c tm d:/c1.json
MongoDB文档增删改查(CRUD)
-
C增
语法:db.集合名.insert(JSON数据)
说明:集合存在-直接插入数据,集合不存在-隐式创建
练习:在test2数据库的c1集合中插入数据(姓名zhangsan年龄18)
use test2 db.c1.insert({name:'zhangsan',age:18}) 注意1:数据库和集合不存在隐式创建 注意2:对象的键统一不加引号方便看,但查看集合数据时系统会自动加 注意3:mongodb会给每条数据增加一个全球唯一的_id键(时间戳+机器码+PID+计数器)
-
思考1:是否可以自定义_id值?
可以,只需要给插入的JSON数据增加_id键即可覆盖(实战强烈不建议)
-
思考2:如何一次性插入多条数据?
传递数组,数组中写一个个JSON数据即可
db.c1.insert([ {name:'zhangsan',age:23}, {name:'lisi',age:24}, {name:'wangwu',age:25} ])
-
思考3:如何快速插入10条数据
mogodb底层使用JS引擎实现的,支持部分js语法 因此可以写for循环
for(var i=1;i<10;i++){ print(i) } 需求:在test2数据库c2集合中插入10条数据,分别为a1,a2...a10 use test2 for(var i=1;i<10;i++){ db.c2.insert({username:'a'+1,age:i}) }
-
-
R查
基础语法:db.集合名.find(条件[,查询的列])
条件 查询所有数据 {}或不写 查询age=6的数据 {age:6} 既要age=6又要性别=男 {age:6,sex:'男'} 查询的列(可选参数 不写 - 查询所有列 {age:1} 只显示age列 {age:0} 除了age列都显示 注意:不管你怎么写系统自定义的_id都会在
升级语法
db.集合名.find({键:值}) 注:值不直接写 db.集合名.find({ 键:{ 运算符:值 } })
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4pJwhJok-1603856560466)(D:\Desk\学习总结\图片\image-20200927011055762.png)]
练习
-
查询所有数据(格式化)
db.c1.find().pretty()
-
只显示name列
db.c1.find({},{name:1})
-
查询年龄大于18的数据
db.c1.find({age:{$gt:18}})
-
查询年龄为5,8,10的数据
db.c1.find({age:{$in:[5,8,10]}})
-
-
U改
基础语法:db.集合名.update(条件,新数据[,是否新增,是否修改多条])
是否新增:指条件匹配不到数据则插入(true是 插入,false否 不插入默认) 是否修改多条:指将匹配的数据都修改(true是,false否某人)
升级语法
db.集合名.update(条件,新数据) {修改器:{键:值}}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uje1LdHH-1603856560483)(D:\Desk\学习总结\图片\image-20201010223426600.png)]
练习
-
准备工作
use test1 for(var i=1;i<=10;i++){ db.c1.insert({"name":"zs"+i,"age":i}) }
-
练习1:将{name:“zs1”}改为{name:“zs2”}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5EPcTXl7-1603856560490)(D:\Desk\学习总结\图片\image-20201010223113240.png)]
发现:默认是替换,不是修改
解决:使用升级语法 修改器
需求:使用修改器将zs2的姓名改为zs22
语法:db.c1.update({name:‘zs2’},{$set:{name:‘zs22’}})
-
练习2:给{name:‘zs10’}的年龄加2岁或者减2岁
db.c1.update({name:'zs10'},{$inc:{age:2}})
-
练习3:修改器综合练习
插入数据:db.c2.insert(name:‘zs’,age:23,sex:‘男’,heigh:111);
完成需求:
name 改成 lisi
age 增加 124
sex 改成 gender
height 删除
db.c2.update({name:'zs'},{name:'lisi'}) #错误替换 {$set:{name:'lisi'}} {$inc:{age:124}} {$rename:{sex:gender}} {$unset:{height:true}} #多个组合器组合 db.c2.update({name:'zs'},{ $set:{name:'lisi'}, $inc:{age:124}, $rename:{sex:'gender'}, $unset:{height:true} })
-
练习4:验证语法最后两个参数(了解)
验证:是否新增true是 false否,修改name等于zs30的年龄30岁
db.c1.update({name:'zs30'},{$set:{age:30}}) 默认false db.c1.update({name:'zs30'},{$set:{age:30}},true)
验证:是否修改多条数据true是,false否默认
# 将所有c1集合中的所有数据改为10岁 db.c1.update({},{$set:{age:10}},false,true)
-
-
D删除
语法:db.集合名.remove(条件[,是否删除一条])
注意:是否删除一条true是,false否 默认
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N8B27P7R-1603856560496)(D:\Desk\学习总结\图片\image-20201010232849959.png)]
数据库设计流程
根据UI设计稿
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CJbw6onh-1603856560499)(D:\Desk\学习总结\图片\image-20201010234537510.png)]
- 确定功能模块所属集合
- 确定集合字段
UI设计稿每个展示内容对应一个字段
创建于字段
更新于字段
状态字段
最后:先中文、后英文
注意:上述规则照顾基础差的,如果大神 或 久而久之 就变成肌肉记忆 下意识直接创建
练习
-
需求:根据教学系统,设计存放学生信息的集合,并插入20条测试数据
-
代码
1.先中文 集合名:学生集合 集合字段(看UI设计稿):编号、学号、姓名、电话、性别、年龄、学历、备注 2.再英文 use student for(var num=1;num<=20;num++){ db.stu.insert({ id:num, no:'2020_'+num, uname:'zhangsan'+num, tel:'123456', sex:'女', age:num, edu:'研究生', remark:'非常好' }) }
MongoDB排序
-
语法:db.集合名.find().sort(JSON数据)
-
说明:键-就是要排序的列 值:1升序 -1降序
-
练习:年龄升序&降序
# 准备数据 use test2; db.c1.insert({_id:1,name:'a',sex:1,age:1}) db.c1.insert({_id:2,name:'a',sex:1,age:2}) db.c1.insert({_id:3,name:'b',sex:2,age:3}) db.c1.insert({_id:4,name:'c',sex:2,age:4}) db.c1.insert({_id:5,name:'d',sex:2,age:5}) db.c1.find() # 年龄升序 db.c1.find().sort({age:1})
MongoDB分页(limit和skip方法)
- 语法:db.集合名.find().sort().skip(数字).limit(数字)
- 说明:skip跳过指定数量(可选),limit限制查询数量
- 练习:1.年龄降序查询2条,2.年龄降序跳过2条并查询两条
# 1.年龄降序查询2条
db.c1.find().sort({age:-1}).limit(2)
# 2.年龄降序跳过2条并查询两条
db.c1.find().sort({age:-1}).skip(2).limit(2)
MongoDB聚合查询
聚合查询:把数据聚起来统计
-
语法
db.集合名.aggregate([ {管道:{表达式}} ])
-
常用管道
$group 将集合中的文档分组,用于统计结果 $match 过滤数据,只要输出符合条件的文档 $sort 聚合数据进一步排序 $skip 跳过指定文档数 $limit 限制集合数据返回文档数 ....
-
常用表达式
$sum 总和 $sum:1同count表示统计 $avg 平均 $min 最小值 $max 最大值 ....
-
练习
-
准备数据
use test3 db.c1.insert({_id:1,name:'a',sex:1,age:1}) db.c1.insert({_id:2,name:'a',sex:1,age:2}) db.c1.insert({_id:3,name:'b',sex:2,age:3}) db.c1.insert({_id:4,name:'c',sex:2,age:4}) db.c1.insert({_id:5,name:'d',sex:2,age:5})
-
练习1 统计男生、女生的总年龄
db.c1.aggregate([ { $group:{ _id:'$sex', rs:{$sum:'$age'} } } ])
-
练习2 统计男生、女生的总人数
db.c1.aggregate([ { $group:{ _id:'$sex', rs:{$sum:1} } } ])
-
练习3 求学生总数和平均年龄
db.c1.aggregate([ { $group:{ _id:null, total_num:{ $sum:1 }, total_avg:{ $avg:'$age' } } } ])
-
练习3 查询男生、女生人数,按人数升序
db.c1.aggregate([ { $group:{ _id:'$sex', rs:{ $sum:1 } } }, { $sort:{ rs:1 } } ])
-
MongoDB优化索引
-
语法
# 创建索引 db.集合名.createIndex(待创建索引的列[,额外选项]) # 参数 带创建索引的列:{键:1,...,键:-1} 1 升序 -1降序 例如{age:1}表示创建age索引并按照升序的方式存储 额外选项:设置索引的名称或唯一索引等等 # 删除索引 全部删除:db.集合名.dropIndexes() 删除指定:db.集合名.dropIndex(索引名) # 查看索引 db.集合名.getIndexes()
-
练习
-
准备数据
// 选择数据库 use test4 // 向数据库中插入数据 for(var i=0;i<100000;i++){ db.c1.insert({name:'aaa'+i,age:i}) }
-
练习1 给name添加普通索引
db.c1.createIndex({name:1})
-
练习2 删除name索引
db.c1.dropIndex('name_1')
-
练习3 给name创建索引并起名name_index
db.c1.createIndex({name:1},{name:'name_index'})
-
-
创建复合/组合索引
-
语法
db.集合名.create({键1:方式,键2:方式})
-
给name和age添加组合索引
db.c1.createIndex({name:1,age:1})
-
-
创建唯一索引
-
语法
db.集合名.create(待添加索引的列,{unique:列名})
-
-
练习
-
练习1 删除全部索引(系统的不会删)
db.c1.dropIndexes()
-
练习2 创建唯一索引
db.c1.createIndex({name:1},{unique:'name'})
-
练习3 测试唯一索引 插入两次相同数据
db.c1.insert({name:'a'}) db.c1.insert({name:'a'})
-
分析索引
-
语法
db.集合名.find().explain('executionStats')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kqSAy12d-1603856560501)(D:\Desk\学习总结\图片\image-20201011231641491.png)]
-
索引的扫描方式
- COLLSCAN 全表扫描
- INSCAN 索引扫描
- FETCH 根据索引去检索指定document
-
选择规则(如何选择合适的列创建索引)
- 为常做条件、排序、分组的字段建立索引
- 选择唯一性索引
- 选择较小的数据列,为较长的字符串使用前缀索引
MongoDB权限机制
-
语法
// 创建账号 db.createUser({ "user": '账号', "pwd": '密码', "roles": [{ role: '角色', db: '所属数据库' }] })
-
角色
# 角色种类 超级用户角色:root 数据库用户角色:read、readWrite 数据库管理角色:dbAdmin、userAdmin 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager 备份恢复角色:backup、restore 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnydDatabase # 角色说明 root:只在admin数据库中可用。超级账号,超级权限 read:允许用户读取指定数据库 readWrite:允许用户读写指定数据库
-
开启验证模式(用户需要输入账号密码才能登录使用)
# 步骤1 添加超级管理员 use admin db.createUser({ 'user': 'admin', 'pwd': 'admin888', 'roles': [{ role: 'root', db: 'admin' }] }) # 步骤2 退出卸载服务 bin\mongod --remove 注意:DOS窗口必需以管理员身份允许 # 步骤3 重新安装需要输入账号密码的服务(注:在原来安装命令基础上加--auth即可) bin\mongod --install --dbpath D:\MongoDB\Server\3.4\data --logpath D:\MongoDB\Server\3.4\logs\mongo2.log --auth # 步骤4 启动服务->登录测试 mongo show dbs # 默认看不到数据库 # 认证身份 方法1 mongo 服务器IP地址:端口/数据库 -u 用户名 -p 密码 方法2 a-先登录 b-选择数据库 c-输入db.auth(用户名,密码)
-
练习
-
添加用户shop1可以读shop数据库
# 注意 选择数据库 用户属于数据库 use shop ## shop1 db.createUser({ 'user': 'shop1', 'pwd': 'admin888', 'roles': [{ role: 'read', db: 'shop' }] }) ## shop2 db.createUser({ 'user': 'shop2', 'pwd': 'admin888', 'rolse': [{ role: 'readWriter', db: 'shop' }] })
-
验证
mongo localhost:27017/shop -u shop1 -p admin888 #可读不可写 db.goods.find() # 正确执行 db.goods.insert({name: 'zhangsan'}) # 报错 # ------------------------------------------------------- mongo localhost:27017/shop -u shop1 -p admin888 #可读可写 db.goods.find() # 正确执行 db.goods.insert({name: 'zhangsan'}) # 正确执行
-
备份数据库mongodump
-
语法
导出数据库语法:mongodump -h -port -u -p -d -o 导出语法说明 -h host 服务器ip地址 (一般不写 默认本机 -port 端口(一般不写 默认27017 -u user 账号 -p pwd 密码 -d database 数据库 (注意:不写导出全部 -o open 备份到指定目录下
-
练习(备份所有数据):mongodump -u admin -p admin888 -o d:\bak
-
练习(备份指定数据):mongodump -u admin -p admin888 -d test -o d:\bak2
还原数据库mongorestore
-
语法
导入数据库语法:mongorestore -h -port -u -p -d --drop 备份数据目录 导入数据库说明 -h host 服务器ip地址 (一般不写 默认本机 -port 端口(一般不写 默认27017 -u user 账号 -p pwd 密码 -d database 数据库 (注意:不写还原全部 --drop 先删除数据库再导入,不写则覆盖
-
练习(还原所有数据):mongorestore -u admin -p admin888 --drop d:\bak
-
练习(还原指定数据):mongorestore -u admin -p admin888 -d test --drop d:\bak2\test
接口
- 文档
- 返回json或xml数据格式
RESTful架构需要满足什么条件
订单模块
/order get
/order post
/order/编号 put
/order/编号 delete
- 项目所有模块有统一的标准
- 看URL就知道要操作的资源是什么(也就是那个模块)
- 看Http Method就知道操作动作是什么,是添加(post)还是删除(delete)
- 看Http Status Code就知道操作结果如何,是成功(200)还是内存错误(500)
java操作MongoDB
-
导入配置文件
//保证版本相同 <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver</artifactId> <version>3.12.7</version> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver-core</artifactId> <version>3.12.7</version> </dependency>
-
java代码–查询
//创建连接 MongoClient client = new MongoClient("127.0.0.1",27017); //获取操作的数据库 MongoDatabase database = client.getDatabase("test"); //获取集合 MongoCollection<Document> collection = database.getCollection("user"); //按照条件进行查询 //第一种 /*Map<String, Object> map = new HashMap<String, Object>(); map.put("name","zhangsan");*/ //BasicDBObject bson = new BasicDBObject("name","zhangsan"); //BasicDBObject bson = new BasicDBObject(map); //第二种 不能支持多个条件传入 Bson bson = Filters.eq("name", "zhangsan"); //获取文档 FindIterable<Document> iterable = collection.find(bson); //循环获取内容 for (Document document : iterable) { System.out.println(document.getString("name")); } //关闭连接 client.close();
-
新增
//创建连接 MongoClient client = new MongoClient("127.0.0.1",27017); //获取操作的数据库 MongoDatabase database = client.getDatabase("test"); //获取集合 MongoCollection<Document> collection = database.getCollection("user"); Map<String, Object> map = new HashMap<String, Object>(); map.put("name","wangwu"); map.put("sex","男"); map.put("age",25); Document document = new Document(map); //插入数据 collection.insertOne(document); //关闭连接 client.close();
-
删除
//创建连接 MongoClient client = new MongoClient("127.0.0.1",27017); //获取操作的数据库 MongoDatabase database = client.getDatabase("test"); //获取集合 MongoCollection<Document> collection = database.getCollection("user"); //一次就删除一条 Bson bson = Filters.eq("name", "wangwu"); collection.deleteOne(bson); System.out.println("删除成功"); //关闭连接 client.close();
-
更新
//创建连接 MongoClient client = new MongoClient("127.0.0.1",27017); //获取操作的数据库 MongoDatabase database = client.getDatabase("test"); //获取集合 MongoCollection<Document> collection = database.getCollection("user"); //更新数据 Bson bson = Filters.eq("name", "zhangsan"); Document document = new Document("$set",new Document("age",23)); collection.updateOne(bson,document); System.out.println("更新成功"); //关闭连接 client.close();
Springboot操作MongoDb
-
导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
-
配置yml
spring: data: mongodb: host: 127.0.0.1 database: test
-
实体类
@Data @NoArgsConstructor @AllArgsConstructor @Document(collation = "user") public class Person { @Id private String id; @Field("name") private String name; @Field("sex") private String sex; @Field("age") private Integer age; }
-
核心代码
@Autowired private MongoTemplate mongoTemplate; @Override public void save(Person person) { mongoTemplate.save(person); } @Override public void update(Person person) { //条件 Query query = new Query(Criteria.where("id").is(person.getId())); //内容 Update update = new Update(); update.set("age",35); update.set("sex","女"); mongoTemplate.updateFirst(query,update,Person.class); } @Override public List<Person> findAll() { return mongoTemplate.findAll(Person.class); } @Override public void delete(String id) { Person person = mongoTemplate.findById(id, Person.class); mongoTemplate.remove(person); }