MongoDB
对于社交类软件的功能特点:
数据量会随着用户数增大而增大
读多写少
价值较低
非好友看不到其动态内容
地理位置的查询
……
针对以上特点,我们来分析一下:
mysql:关系型数据库(效率低)
redis:redis缓存(微博,效率高,数据格式不丰富)
对于数据量大而言,显然不能够使用关系型数据库进行存储,我们需要通过MongoDB进行存储
对于读多写少的应用,需要减少读取的成本
比如说,一条SQL语句,单张表查询一定比多张表查询要快
数据库应用:
mongodb:存储业务数据(圈子,推荐的数据,小视频数据,点赞,评论等)
redis:承担的角色是缓存层(提升查询效率)
mysql:存储和核心业务数据,账户
MongoDB是一个开源、高性能、支持海量数据存储的文档型数据库
是NoSQL数据库产品中的一种,是最像关系型数据库(MySQL)的非关系型数据库(不支持表关系:只能操作单表)
MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
官网:https://www.mongodb.com
数据存储:内存 + 磁盘
高扩展性:内置数据分片
MongoDB与Redis和Mysql的对比
与Redis的对比
Redis纯内存数据库,内存不足触发淘汰策略
结构化存储格式(Bson),方便扩展
与MySQL的对比
MongoDB不支持事务和多表操作
MongoDB支持动态字段管理
查询效率对比
Redis > MongoDB > MySQL
Mongodb的适用场景
游戏装备数据、游戏道具数据
特征:修改频度较高
物流行业数据
特征:地理位置信息,海量数据
直播数据、打赏数据、粉丝数据
特征:数据量大,修改频度极高
日志数据
特征:数据量巨大,结构多变
体系结构与术语
数据格式
MongoDB中使用Bson存储数据( Binary JSON ),一种类似Json的数据格式。
docker安装MongoDB
拉取镜像
docker pull mongo
创建容器
docker run --name mongo-service -p 27017:27017 -v ~/data/mongodata:/data -d mongo
注:
虚拟机中已经以docker-compose的形式提供了MongoDB容器。不需要重新拉取部署
企业中MongoDB往往需要配置操作用户密码
启动容器
#进入base目录
cd /root/docker-file/base/
#批量创建启动容器,其中已经包含了redis,zookeeper,mongodb容器
docker-compose up -d
#查看容器
docker ps -a
mongoDB已经启动,对外暴露了27017的操作端口
MongoDB入门
基础命令
数据库操作
1 #查看所有数据库 2 show dbs 3 #通过use关键字切换数据库 4 use testdb 5 #删除数据库 6 db.dropDatabase()
新增数据
在MongoDB中,存储的文档结构是一种类似于json的结构,称之为bson(全称为:Binary JSON)
#语法:db.表名.insert(json字符串)
> db.user.insert({id:1,username:'zhangsan',age:20})
> db.user.find() #查询数据
修改数据
db.collection.update( <query>, <update>, [ upsert: <boolean>, multi: <boolean>, writeConcern: <document> ] )
注:
query : update的查询条件,类似sql update查询内where后面的。
update : update的对象和一些更新的操作符(如$,$inc.$set)等,也可以理解为sql update查询内set后面的
upsert (默认false ) : 可选,如果不存在update的记录,是否插入新数据,true为插入,默认是false,不插入。
multi(默认false ) : 可选,默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern :可选,抛出异常的级别。
#查询全部
> db.user.find()
#更新数据
> db.user.update({id:1},{$set:{age:22}})
#更新不存在的数据,默认不会新增数据
> db.user.update({id:3},{$set:{sex:1}})
#如果设置第一个参数为true,就是新增数据
> db.user.update({id:3},{$set:{sex:1}},true)
删除数据
db.collection.remove( <query>, { justOne: <boolean>, writeConcern: <document> } )
注:
query :(可选)删除的文档的条件。
justOne: (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
writeConcern :(可选)抛出异常的级别。
#插入4条测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})
> db.user.remove({age:22},true)
#删除所有数据
> db.user.remove({})
查询数据
db.collection.find([query],[fields])
注:
query :可选,使用查询操作符指定查询条件
fields :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
在查询时,通过query指定查询条件:
操作 说明 范例 RDBMS中的类似语句
等于 {<key>:<value>} db.col.find({"by":"程序员"}).pretty() where by = '程序员'
小于 {<key>:{$lt:<value>}} db.col.find({"likes":{$lt:50}}).pretty() where likes < 50
小于或等于 {<key>:{$lte:<value>}} db.col.find({"likes":{$lte:50}}).pretty() where likes <= 50
大于 {<key>:{$gt:<value>}} db.col.find({"likes":{$gt:50}}).pretty() where likes > 50
大于或等于 {<key>:{$gte:<value>}} db.col.find({"likes":{$gte:50}}).pretty() where likes >= 50
不等于 {<key>:{$ne:<value>}} db.col.find({"likes":{$ne:50}}).pretty() where likes != 50
#插入测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})
db.user.find() #查询全部数据
db.user.find({},{id:1,username:1}) #只查询id与username字段
db.user.find().count() #查询数据条数
db.user.find({id:1}) #查询id为1的数据
db.user.find({age:{$lte:21}}) #查询小于等于21的数据
db.user.find({$or:[{id:1},{id:2}]}) #查询id=1 or id=2
#分页查询:Skip()跳过几条,limit()查询条数
db.user.find().limit(2).skip(1) #跳过1条数据,查询2条数据
db.user.find().sort({id:-1}) #按照id倒序排序,-1为倒序,1为正序
索引
为了提高查询效率,MongoDB中也支持索引。
#查看索引
db.user.getIndexes()
#创建索引
#db.user.createIndex({'age':1})
注:1 :升序索引 -1 :降序索引
Springboot整合MongoDB
Spring-data对MongoDB做了支持,使用spring-data-mongodb可以简化MongoDB的操作,封装了底层的mongodb-driver。
地址:https://spring.io/projects/spring-data-mongodb
使用Spring-Data-MongoDB很简单,只需要如下几步即可:
导入起步依赖
编写配置信息
编写实体类(配置注解 @Document,@Id)
操作mongodb
注入MongoTemplate对象,完成CRUD操作
编写Repository接口,注入接口完成基本Crud操作
1 <parent> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-parent</artifactId> 4 <version>2.3.9.RELEASE</version> 5 </parent> 6 <dependencies> 7 <dependency> 8 <groupId>org.springframework.boot</groupId> 9 <artifactId>spring-boot-starter-data-mongodb</artifactId> 10 </dependency> 11 <dependency> 12 <groupId>org.springframework.boot</groupId> 13 <artifactId>spring-boot-starter-test</artifactId> 14 <scope>test</scope> 15 </dependency> 16 </dependencies>
第二步,编写application.yml配置文件:
1 spring: 2 data: 3 mongodb: 4 uri: mongodb://192.168.136.160:27017/test
第三步,编写启动类
1 @SpringBootApplication 2 public class MongoApplication { 3 4 public static void main(String[] args) { 5 SpringApplication.run(MongoApplication.class, args); 6 } 7 }
1 @Data 2 @Document(value="tb_person") 3 public class Person { 4 @Id 5 private ObjectId id; 6 @Field("myname") 7 private String name; 8 private int age; 9 private String address; 10 }
第二步,通过MongoTemplate完成CRUD操作
1 @RunWith(SpringRunner.class) 2 @SpringBootTest(classes = MongoApplication.class) 3 public class MongoTest { 4 /** 5 * 1、注入MongoTemplate对象 6 * 2、调用对象方法完成数据的CRUD 7 */ 8 @Autowired 9 private MongoTemplate mongoTemplate; 10 11 //保存 12 @Test 13 public void testSave() { 14 Person person = new Person(); 15 person.setName("张三"); 16 person.setAge(18); 17 person.setAddress("北京"); 18 mongoTemplate.save(person); 19 } 20 21 /** 22 * 查询所有 23 */ 24 @Test 25 public void testFindAll() { 26 List<Person> list = mongoTemplate.findAll(Person.class); 27 for (Person person : list) { 28 System.out.println(person); 29 } 30 } 31 32 /** 33 * 条件查询 34 */ 35 @Test 36 public void testFind() { 37 //1、创建Criteria对象,并设置查询条件 38 Criteria criteria = Criteria.where("myname").is("张三") 39 .and("age").is(18) 40 ;//is 相当于sql语句中的= 41 //2、根据Criteria创建Query 42 Query query = new Query(criteria); 43 //3、查询 44 List<Person> list = mongoTemplate.find(query, Person.class);//Query对象,实体类对象字节码 45 for (Person person : list) { 46 System.out.println(person); 47 } 48 } 49 50 /** 51 * 分页查询 52 */ 53 @Test 54 public void testPage() { 55 int page = 1; 56 int size = 2; 57 //1、创建Criteria对象,并设置查询条件 58 Criteria criteria = Criteria.where("age").lt(50); //is 相当于sql语句中的= 59 //2、根据Criteria创建Query 60 Query queryLimit = new Query(criteria) 61 .skip((page -1) * size) //从第几条开始查询 62 .limit(size) //每页查询条数 63 .with(Sort.by(Sort.Order.desc("age"))); 64 //3、查询 65 List<Person> list = mongoTemplate.find(queryLimit, Person.class); 66 for (Person person : list) { 67 System.out.println(person); 68 } 69 } 70 71 72 /** 73 * 更新 74 */ 75 @Test 76 public void testUpdate() { 77 //1、构建Query对象 78 Query query = Query.query(Criteria.where("id").is("61275c3980f68e67ab4fdf25")); 79 //2、设置需要更新的数据内容 80 Update update = new Update(); 81 update.set("age", 10); 82 update.set("myname", "lisi"); 83 //3、调用方法 84 mongoTemplate.updateFirst(query, update, Person.class); 85 } 86 87 //删除 88 @Test 89 public void testDelete() { 90 //1、构建Query对象 91 Query query = Query.query(Criteria.where("id").is("5fe404c26a787e3b50d8d5ad")); 92 mongoTemplate.remove(query, Person.class); 93 } 94 }