MongoDB的基本介绍及SpringBoot整合MongoDB
1 MongoDB基本概念
1.1 NoSQL
NoSQL(Not Only SQL),意为反SQL。
NoSQL好处:
- 对数据库高并发读写
- 对海量数据的高效率存储和访问
- 对数据库的高可扩展性和高可用性
NoSQL不足:
- 数据库事务的一致性需求
- 数据库的写实性和读时性需求
- 对复杂的SQL查询,特别时多表联查的需求
1.2 MongoDB
1.2.1 与关系型数据库对应关系
MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
-
部分术语:
-
与关系型数据库的对应关系:
注意:
1. 文档中键/值对是有序的
2. 文档中的值不仅可以是String还是可以其他的【类比JSON】
3. MongoDB区分大小写
4. MongoDB不能有重复的键
5. 文档的键是字符串。(存在特例)
文档键命名规范:
1、键不能含有\0 (空字符)。这个字符用来表示键的结尾。
2、.和$有特别的意义,只有在特定环境下才能使用。
3、以下划线"_"开头的键是保留的(不是严格要求的)。
1.2.2 数据类型
1.2.3 适用场景
- 适用场景:
- 网站数据:Mongo适合实时的插入、更新与查询数据
- 缓存:性能高,可以作为缓存使用
- 数据价值低:传统的RDB有些比较昂贵
- 高伸缩:适合由十台或数百台组成的数据库
- 存储对象或JSON
- 不适用:
- 高事务性系统
- 传统的商业智能应用
1.2.4 基于Docker安装和使用MongoDB
- 启动docker
sudo systemctl start docker
- 拉取mongoDB镜像
此处拉取最新的mongo镜像
docker pull mongo:latest
- 创建和启动容器
docker run -d --restart=always -p 27017:27017 --name mymongo -v/data/db:/data/db -d mongo
- 进入容器
docker exec -it mymongo /bin/bash
- 进入mongo自带的客户端进行操作(就像登录MySQL的客户端一样)
mongo
常见命令汇总:
1、 Help查看命令提示
db.help();
2、 切换/创建数据库
use test
如果数据库不存在,则创建数据库,否则切换到指定数据库
3、 查询所有数据库
show dbs;
4、 删除当前使用数据库
db.dropDatabase();
5、 查看当前使用的数据库
db.getName();
6、 显示当前db状态
db.stats();
7、 当前db版本
db.version();
8、 查看当前db的链接机器地址
db.getMongo〇;
【1】Insert
> db.User.save({name:'zhangsan',age:21,sex:true})
> db.User.find()
{"_id": Objectld("4f69e680c9106ee2ec95da66"), "name": "zhangsan", "age": 21,
"sex": true}
MongoDB会自动为我们生成ID
【2】Query
1、 Where
# select * from User where name = 'zhangsan'
> db.User.find({name:"zhangsan"})
2、 FIELDS
# select name, age from User where age = 21
> db.User.find({age:21}, {'name':1, 'age':1})
3、SORT
`在 MongoDB 中使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,
并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。`
# select * from User order by age
> db.User.find().sort({age:1})
4、SUCE(分页)
在 MongoDB 中使用 limit()方法来读取指定数量的数据,skip()方法来跳过指定数量的数据
# select * from User skip 2 limit 3
> db.User.find().skip(0).limit(3)
5、IN
# select * from User where age in (21, 26, 32)
> db.User.find({age:{$in:[21,26,32]}})
6、COUNT
# select count(*) from User where age >20
> db.User.find({age:{$gt:20}}).count()
7、OR
# select * from User where age = 21 or age = 28
> db.User.find({$or:[{age:21}, {age:28}]})
【4】UPDATE
# update Userset age = 100, sex = 0 where name = 'user1'
> db.User.update({name:"zhangsan"}, {$set:{age:100, sex:0}})
Update()有几个参数需要注意。
db.collection.update(criteria, objNew, upsert, mult)
criteria:需要更新的条件表达式
objNew:更新表达式
upsert:如FI标记录不存在,是否插入新文档。
multi:是否更新多个文档。
【5】REMOVE
> db.User.remove(id)
//移除对应id的行
> db.User.remove({})
//移除所有
2 SpringBoot整合MongoDB
2.1 创建项目引入依赖
创建一个Boot项目,在pom文件中,引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
2.2 修改配置文件为Mongo地址
spring.data.mongodb.uri=mongodb://47.93.118.241:27017/test
2.3 使用封装好的类完成CRUD开发
2.3.1 基于MongoTemplate开发CRUD
①添加实体
@Data
@Document("User")
public class User {
@Id
private String id;
private String name;
private Integer age;
private String email;
private String createDate;
}
②实现
常用方法及Query对象:
常用方法
mongoTemplate.findAll(User.class): 查询User文档的全部数据
mongoTemplate.findById(<id>, User.class): 查询User文档id为id的数据
mongoTemplate.find(query, User.class);: 根据query内的查询条件查询
mongoTemplate.update(query, update, User.class): 修改
mongoTemplate.remove(query, User.class): 删除
mongoTemplate.insert(User): 新增
Query对象
1、创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
2、 精准条件:criteria.and(“key”).is(“条件”)
模糊条件:criteria.and(“key”).regex(“条件”)
3、封装条件:query.addCriteria(criteria)
4、大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)
小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)
5、Query.addCriteria(new Criteria().andOperator(gt,lt));
6、一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
7、排序 :query.with(new Sort(Sort.Direc
update 为更新操作符
upsert 为布尔型可选项,表示如果不存在 update 的记录,是否插入这个新的文档。true 为插入;默认为 false,不插入
【Insert、Query】
@SpringBootTest
public class DemomogoApplicationTests {
@Autowired
private MongoTemplate mongoTemplate;
//添加
@Test
public void createUser() {
User user = new User();
user.setAge(20);
user.setName("test");
user.setEmail("4932200@qq.com");
User user1 = mongoTemplate.insert(user);
System.out.println(user1);
//自动生成的id:6339085189a1b05972d7682b
}
//查询所有
@Test
public void findUser(){
//再添加一个用户
User user = new User();
user.setAge(23);
user.setName("CR7");
mongoTemplate.insert(user);
List<User> userList = mongoTemplate.findAll(User.class);
System.out.println(userList);
//[User(id=6339085189a1b05972d7682b, name=test, age=20, email=4932200@qq.com, createDate=null),
// User(id=633953a28d2c574bbf3e0d1e, name=CR7, age=23, email=null, createDate=null)]
}
//根据id查询
@Test
public void getById(){
User user = mongoTemplate.findById("6339085189a1b05972d7682b", User.class);
System.out.println(user);
//User(id=6339085189a1b05972d7682b, name=test, age=20, email=4932200@qq.com, createDate=null)
}
@Test
public void findUserByCon(){
//构造条件,相当于where后面的语句
Query query = new Query(Criteria.where("name").is("test")
.and("age").is(20));
List<User> userList = mongoTemplate.find(query, User.class);
System.out.println(userList);
//[User(id=6339085189a1b05972d7682b, name=test, age=20, email=4932200@qq.com, createDate=null)]
}
//模糊查询
@Test
public void findUsersLikeName(){
String name = "est";
//正则
String regex = String.format("%s%s%s", "^.*", name, ".*$");
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Query query = new Query(Criteria.where("name").regex(pattern));
List<User> userList = mongoTemplate.find(query, User.class);
System.out.println(userList);
}
//分页查询
@Test
public void findUserByPage(){
String name = "est";
int pageNo = 1;
int pageSize = 10;
Query query = new Query();
String regex = String.format("%s%s%s", "^.*", name, ".*$");
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
query.addCriteria(Criteria.where("name").regex(pattern));
int totalCount = (int)mongoTemplate.count(query, User.class);
List<User> userList = mongoTemplate.find(query.skip((pageNo - 1) * pageSize).limit(pageSize), User.class);
Map<String, Object> pageMap = new HashMap<>();
pageMap.put("list", userList);
pageMap.put("totalCount", totalCount);
System.out.println(pageMap);
//{list=[User(id=6339085189a1b05972d7682b, name=test, age=20, email=4932200@qq.com, createDate=null)], totalCount=1}
}
}
【UPDATE、REMOVE】
//修改
@Test
public void updateUser(){
User user = mongoTemplate.findById("6339085189a1b05972d7682b", User.class);
user.setName("Neymar");
user.setAge(28);
user.setEmail("28172349@qq.com");
Query query = new Query(Criteria.where("_id").is(user.getId()));
Update update = new Update();
update.set("name", user.getName());
update.set("age", user.getAge());
update.set("email", user.getEmail());
//upsert与update不同,upsert 为布尔型可选项,表示如果不存在 update 的记录,
// 是否插入这个新的文档。true 为插入;默认为 false,不插入
UpdateResult result = mongoTemplate.upsert(query, update, User.class);
long count = result.getModifiedCount();
System.out.println(count);//1
}
//删除操作
@Test
public void delete(){
Query query = new Query(Criteria.where("_id").is("6339085189a1b05972d7682b"));
DeleteResult result = mongoTemplate.remove(query, User.class);
long count = result.getDeletedCount();
System.out.println(count);//1
}
2.3.2 基于MongoRepository开发CRUD
SpringData提供了对Mongodb数据访问的支持,我们继承MongoRepository类,按照SpringData规范就可以了,默认会帮我们实现
SpringData定义方法规范:
1、 不是随便声明的,而需要符合一定的规范
2、 查询方法以find | read | get开头
3、 涉及条件查询时,条件的属性用条件关键字连接
4、 要注意的是:条件属性首字母需要大写
5、 支持属性的级联查询,但若当前类有符合条件的属性则优先使用,而不使用级联属性,
若需要使用级联属性,则属性之间使用_强制进行连接
①创建对应记录(相当于实体类)
@Data
@Document("User")
public class User {
@Id
private String id;
private String name;
private Integer age;
private String email;
private String createDate;
}
②创建UserRepository
@Repository
public interface UserRepository extends MongoRepository<User, String> {
}
③创建测试类
@SpringBootTest
public class MongoTestApplication2 {
@Autowired
private UserRepository userRepository;
//添加
@Test
public void createUser(){
User user = new User();
user.setAge(24);
user.setName("张三");
user.setEmail("41324213@qq.com");
User user1 = userRepository.save(user);
}
//根据id查询
@Test
public void getById(){
User user = userRepository.findById("63395d16b77a6d19b73d6855").get();
System.out.println(user);
}
//条件查询
@Test
public void findUserByCon(){
User user = new User();
user.setName("张三");
Example<User> userExample = Example.of(user);
List<User> userList = userRepository.findAll(userExample);
System.out.println(userList);
//User(id=63395d16b77a6d19b73d6855, name=张三, age=24, email=41324213@qq.com, createDate=null)
}
//模糊查询
@Test
public void findUserLikeName(){
//创建匹配器
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)//改变默认匹配方式:模糊查询
.withIgnoreCase(true);//改变默认大小写忽略方式:忽略大小写
User user = new User();
user.setName("三");
Example<User> userExample = Example.of(user, matcher);
List<User> userList = userRepository.findAll(userExample);
System.out.println(userList);
}
//分页查询
@Test
public void findUserPage(){
Sort sort = Sort.by(Sort.Direction.DESC, "age");
PageRequest pageable = PageRequest.of(0, 10, sort);//0为第一页
//创建匹配器
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)//用模糊查询
.withIgnoreCase(true);//忽略大小写
User user = new User();
user.setName("三");
//创建实例
Example<User> example = Example.of(user, matcher);
Page<User> pages = userRepository.findAll(example, pageable);
System.out.println(pages.getTotalElements());//1
}
//修改
@Test
public void update(){
User user = userRepository.findById("63395d16b77a6d19b73d6855").get();
user.setName("张三儿~");
user.setAge(29);
User save = userRepository.save(user);
System.out.println(save);
//User(id=63395d16b77a6d19b73d6855, name=张三儿~, age=29, email=41324213@qq.com, createDate=null)
}
//删除
@Test
public void delete(){
userRepository.deleteById("63395d16b77a6d19b73d6855");
}
}