• 22-08-08 西安 尚医通(04)MongoDB命令、MongoTemplate、MongoRepository


    MongoDB

    1、NoSQL

    NoSQL(NoSQL = Not Only SQL),指的是非关系型的数据库

    为什么使用NoSQL :

    1、对数据库高并发读写。请求量大

    2、对海量数据的高效率存储和访问。 数据量大

    3、对数据库的高可扩展性和高可用性。

    noSQL缺点:

    1、数据库事务一致性需求,形同虚设

    2、对复杂的SQL查询,特别是多表关联查询的需求

    2、MongoDB

    MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。集群、分片、加节点的方式实现扩容

    MongoDB 将数据存储为一个文档,存储格式是BSON,数据结构由键值对(key=>value)组成。

    BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON,它和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。

    --------------------------------

    MongoDB特点

    1、MongoDB 是一个面向文档存储的数据库。

    2、你可以在MongoDB记录中设置任何属性的索引来实现更快的排序 。 

    3、如果负载的增加(需要更多的存储空间和更强的处理能力),它可以分布在计算机网络中的其他节点上这就是所谓的分片

    4、Mongo支持丰富的查询表达式。

    5、MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。

    一个mongodb中可以建立多个数据库,文档是一组键值(key-value)对(即BSON)。

    MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型。

    集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。

    -------------------------------

    MongoDB适用场景

    1、网站数据:Mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。

    2、缓存:由于性能很高,Mongo也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数据源过载。

    3、大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。


    3、使用Docker安装MongoDB

    1.拉取镜像

    docker pull mongo:4.4.8        

    2.data目录赋予777权限-目录挂载

    chmod 777 /data/

    3.创建和启动容器

    docker run -id --restart=always -p 27017:27017 --name mymongo -v /data/db:/data/db mongo:4.4.8

    4.进入容器

    docker exec -it mymongo /bin/bash

    5.使用MongoDB客户端操作

    mongo


    4、MongoDB常见数据类型


    5、MongoDB基本命令

    下表列出了 RDBMS 与 MongoDB 对应的术语 

    常用操作如下:

    1.show dbs #查询所有的数据库

    还有一个默认的test库

    2.use yygh,创建或切换数据库

    3.show tables

    查询当前数据库所有的集合

    4.创建集合、插入文档

    5.无条件查询所有

    多了一个_id,是mongodb自动生成的

    类型:ObjectId类型(bson中特有的一种类型)

    12位,每位2个数字(16进制数据),一共24个字符

    1. 时间戳:时间不断变化的

    2. 机器:主机的唯一标识码。通常是机器主机名的散列值,这样可以确保不同主机生成不同的Objectld ,不产生冲突。

    3. PID:为了确保在同一台机器上并发的多个进程产生的Objectld是唯一的,所以加上进程标识符(PID).

    4. 计数器:后3个字节就是一个自动增加的计数器,确保相同进程同一秒产生的Objectld也是不一样。

    6.无条件删除

    7.根据指定条件删除

    8.根据条件查询

    9.多条件查询


    6、常用操作第一组命令

    field:指定返回的域(字段)

     不要id

    sort排序

    在 MongoDB 中使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。

    升序1

     降序-1

    分页

    在 MongoDB 中使用  skip()方法来跳过指定数量的数据,limit()方法来读取指定数量的数据

     IN

    COUNT

    OR

    AND


    7、常用操作第二组命令

    UPDATE

    满足条件的都要修改

    只改第一个

    Remove

    remove()用于删除单个或全部文档,删除后的文档无法恢复

    根据条件删除

    根据id删除

    索引

    索引通常能够极大的提高查询的效率,索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。

    语法中 age值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。

    创建索引

    聚合

    MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。

    统计各个年龄的人数


    MongoTemplate

    spring-data-mongodb提供了两种方式访问mongodb:

    (1)MongoTemplate

    (2)MongoRepository

    MongoRepository操作简单,MongoTemplate操作灵活;

    1、添加依赖

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframework.bootgroupId>
    4. <artifactId>spring-boot-starter-testartifactId>
    5. <scope>testscope>
    6. dependency>
    7. <dependency>
    8. <groupId>org.springframework.bootgroupId>
    9. <artifactId>spring-boot-starter-data-mongodbartifactId>
    10. dependency>
    11. dependencies>

    2、配置文件配置

    spring.data.mongodb.uri=mongodb://192.168.188.129:27017/test

    3、准备一个实体类User

    1. //@Document映射到哪一个集合
    2. @Data
    3. @Document("User")
    4. public class User {
    5. @Id
    6. private String id;
    7. private String name;
    8. private Integer age;
    9. private String email;
    10. private String createDate;
    11. }

    MongoTemplate方法测试

    常用方法
    mongoTemplate.findAll(User.class): 查询User文档的全部数据
    mongoTemplate.findById(, User.class): 查询User文档id为id的数据
    mongoTemplate.find(query, User.class);: 根据query内的查询条件查询
    mongoTemplate.upsert(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(“条件”)
    5Query.addCriteria(new Criteria().andOperator(gt,lt));
    6、一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
    7、排序 query.withnew Sort(Sort.Direction.ASC, "age"). and(new Sort(Sort.Direction.DESC, "date")))


    测试类前提:

    import org.junit.jupiter.api.Test;
    1. @SpringBootTest
    2. public class MDTest {
    3. @Autowired
    4. private MongoTemplate mongoTemplate;
    5. }

    1、insert 添加

    1. //添加
    2. @Test
    3. public void test1() {
    4. User user = new User();
    5. user.setAge(19);
    6. user.setName("阿肥");
    7. user.setEmail("422eeeee@qq.com");
    8. user.setCreateDate("2022-08-09");
    9. //主键id会自动回填
    10. mongoTemplate.insert(user);
    11. System.out.println(user);
    12. }


    2、updateMulti 修改

    1. //修改
    2. @Test
    3. public void test8(){
    4. Query query = new Query(Criteria.where("name").is("阿广"));
    5. Update update = new Update();
    6. update.set("name","test3");
    7. update.set("age",18);
    8. //修改符合条件的多列
    9. UpdateResult updateResult = mongoTemplate.updateMulti(query, update, User.class);
    10. }


    3、save修改

    1. //修改
    2. @Test
    3. public void test9(){
    4. User user = mongoTemplate.findById("62f0b33218603727b569c41a", User.class);
    5. user.setName("test4");
    6. //user有id save()执行修改指定文档 无id 执行新增操作
    7. mongoTemplate.save(user);
    8. }


    4、remove带条件删除

    1. //带条件删除
    2. @Test
    3. public void test10(){
    4. Query query = new Query(Criteria.where("_id").is("62f0b33218603727b569c41a"));
    5. mongoTemplate.remove(query, User.class);
    6. }


    5、查询所有

    1. //查询所有
    2. @Test
    3. public void test2() {
    4. List userList = mongoTemplate.findAll(User.class);
    5. userList.forEach(u -> {
    6. System.out.println(u);
    7. });
    8. }


    6、根据id查询

    1. //根据id查询
    2. @Test
    3. public void test3() {
    4. User user = mongoTemplate.findById("62f0b33218603727b569c41a", User.class);
    5. System.out.println(user);
    6. }


    7、根据条件查询

    1. //根据条件查询
    2. @Test
    3. public void test4() {
    4. Query query = new Query();
    5. //is方法的参数类型object,但是实际传入的值一定和字段本身的类型要一致
    6. query.addCriteria(Criteria.where("name").is("南哥"));
    7. // Query query = new Query(
    8. // Criteria.where("name").is("test").and("age").is(20) //注意:age是整型,不要加“”
    9. // );
    10. List userList = mongoTemplate.find(query, User.class);
    11. userList.forEach(u -> {
    12. System.out.println(u);
    13. });
    14. }


    8、模糊查询

    1. //模糊查询
    2. @Test
    3. public void test5() {
    4. String name = "est";
    5. //这几行固定格式的,实现模糊查询
    6. String regex = String.format("%s%s%s", "^.*", name, ".*$");
    7. Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
    8. Query query = new Query(Criteria.where("name").regex(pattern));
    9. List userList = mongoTemplate.find(query, User.class);
    10. userList.forEach(u -> {
    11. System.out.println(u);
    12. });
    13. }


    9、分页查询

    1. //分页查询
    2. @Test
    3. public void test6(){
    4. Query query = new Query().skip(0).limit(3);
    5. List userList = mongoTemplate.find(query, User.class);
    6. userList.forEach(u -> {
    7. System.out.println(u);
    8. });
    9. }


    10、带条件的分页查询

    1. //分页条件查询
    2. @Test
    3. public void test7(){
    4. Query query = new Query(Criteria.where("age").is(28))
    5. .skip(0).limit(3);
    6. List userList = mongoTemplate.find(query, User.class);
    7. userList.forEach(u -> {
    8. System.out.println(u);
    9. });
    10. }

    11、mongoTemplate做聚合查询

    要做到页面效果:

    代码先上,真是吓死个人啊

    1. @Override
    2. public Map getRuleSchedule(long page, long limit, String hoscode, String depcode) {
    3. //1.定义查询条件
    4. Criteria criteria = Criteria.where("hoscode").is(hoscode).and("depcode").is(depcode);
    5. //2.定义聚合
    6. Aggregation aggre = Aggregation.newAggregation(
    7. Aggregation.match(criteria),
    8. Aggregation.group("workDate")
    9. .first("workDate").as("workDate")
    10. .sum("reservedNumber").as("reservedNumber")
    11. .sum("availableNumber").as("availableNumber")
    12. .count().as("docCount"),
    13. Aggregation.sort(Sort.Direction.ASC, "workDate"),
    14. Aggregation.skip((page - 1) * limit),
    15. Aggregation.limit(limit)
    16. );
    17. //执行查询
    18. AggregationResults aggregate1 = mongoTemplate.aggregate(aggre, Schedule.class, BookingScheduleRuleVo.class);
    19. List bookingScheduleRuleVoList = aggregate1.getMappedResults();
    20. //3.获取总记录数
    21. Aggregation aggregation = Aggregation.newAggregation(
    22. Aggregation.match(criteria),
    23. Aggregation.group("workDate")
    24. );
    25. AggregationResults aggregate = mongoTemplate.aggregate(aggregation, Schedule.class, BookingScheduleRuleVo.class);
    26. int total = aggregate.getMappedResults().size();
    27. //4. 获取日期对应的星期
    28. for (BookingScheduleRuleVo bookingScheduleRuleVo : bookingScheduleRuleVoList) {
    29. Date workDate = bookingScheduleRuleVo.getWorkDate();
    30. String dayOfWeek = this.getDayOfWeek(new DateTime(workDate));
    31. bookingScheduleRuleVo.setDayOfWeek(dayOfWeek);
    32. }
    33. //5.获取医院名称
    34. String hosname = hospitalService.getByHoscode(hoscode).getHosname();
    35. Map baseMap = new HashMap<>();
    36. baseMap.put("hosname", hosname);
    37. //6. 封装返回值
    38. Map result = new HashMap<>();
    39. result.put("bookingScheduleRuleList", bookingScheduleRuleVoList);
    40. result.put("total", total);
    41. result.put("baseMap", baseMap);
    42. return result;
    43. }
    44. /**
    45. * 根据日期获取星期数据
    46. *
    47. * @param dateTime
    48. * @return
    49. */
    50. private String getDayOfWeek(DateTime dateTime) {
    51. int dayOfWeek = dateTime.getDayOfWeek();
    52. List strings = Arrays.asList("周一", "周二", "周三", "周四", "周五", "周六", "周日");
    53. return strings.get(dayOfWeek - 1);
    54. }

     最主要的点:

    断点:执行查询的效果


     MongoRepository

    SpringData提供了MongoRepository接口,非常方便的实现了增删改查。我们只需要继承MongoRepository接口,按照Spring Data规范就可以了。

    添加一个接口:

    1. @Repository
    2. public interface UserRepository extends MongoRepository {
    3. }

    测试前提:

    1. @SpringBootTest
    2. public class RepositoryMDTest {
    3. @Autowired
    4. private UserRepository userRepository;
    5. }

    1、添加

    1. //添加
    2. @Test
    3. public void test1() {
    4. User user = new User();
    5. user.setAge(28);
    6. user.setName("阿广");
    7. user.setEmail("3322228@qq.com");
    8. user.setCreateDate("22-08-07");
    9. //save方法既可以添加也可以修改,取决于user中有没有id
    10. User user1 = userRepository.save(user);
    11. }

    2、修改

    1. //修改
    2. @Test
    3. public void test2() {
    4. User user = userRepository.findById("62f075ef7843a4005c1c4abe").get();
    5. user.setName("通仔");
    6. user.setAge(26);
    7. User save = userRepository.save(user);
    8. System.out.println(save);
    9. }

    3、查询所有

    1. //查询所有
    2. @Test
    3. public void test3() {
    4. List userList = userRepository.findAll();
    5. System.out.println(userList);
    6. }

    4、根据id查询

    1. //根据id查询
    2. @Test
    3. public void test4() {
    4. User user = userRepository.findById("62f075ef7843a4005c1c4abe").get();
    5. System.out.println(user);
    6. }

    5、根据id删除

    1. //根据id删除
    2. @Test
    3. public void test5() {
    4. userRepository.deleteById("62f075ef7843a4005c1c4abe");
    5. }

    6、查询所有并排序

    1. //查询所有并排序
    2. @Test
    3. public void test6(){
    4. Sort sort = Sort.by(Sort.Direction.DESC, "age");
    5. List userList = userRepository.findAll(sort);
    6. userList.forEach(user -> {
    7. System.out.println(user);
    8. });
    9. }

    7、条件查询

    1. //条件查询
    2. @Test
    3. public void test7(){
    4. User user = new User();
    5. user.setName("阿广");
    6. Example userExample = Example.of(user);
    7. List userList = userRepository.findAll(userExample);
    8. userList.forEach(u -> {
    9. System.out.println(u);
    10. });
    11. }

    8、分页查询

    1. //分页查询
    2. @Test
    3. public void test8(){
    4. //page=0表示第一页
    5. PageRequest pageable = PageRequest.of(0, 2);
    6. Page all = userRepository.findAll(pageable);
    7. List userList = all.getContent();
    8. userList.forEach(u -> {
    9. System.out.println(u);
    10. });
    11. long totalElements = all.getTotalElements();//总记录数
    12. int totalPages = all.getTotalPages();//总页数
    13. System.out.println("总记录数:"+ totalElements);
    14. System.out.println("总页数:"+ totalPages);
    15. }

    9、分页查询并排序

    1. //分页排序写在一块
    2. @Test
    3. public void test9(){
    4. Sort sort = Sort.by(Sort.Direction.DESC, "age");
    5. //page=0表示第一页
    6. PageRequest pageable = PageRequest.of(0, 2,sort);
    7. Page all = userRepository.findAll(pageable);
    8. List userList = all.getContent();
    9. userList.forEach(u -> {
    10. System.out.println(u);
    11. });
    12. long totalElements = all.getTotalElements();//总记录数
    13. int totalPages = all.getTotalPages();//总页数
    14. System.out.println("总记录数:"+ totalElements);
    15. System.out.println("总页数:"+ totalPages);
    16. }

    10、模糊查询

    1. //模糊查询
    2. @Test
    3. public void test10(){
    4. User user = new User();
    5. user.setName("test");
    6. //模糊查询固定格式
    7. ExampleMatcher matcher =
    8. ExampleMatcher
    9. .matching()
    10. .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)//模糊查询
    11. .withIgnoreCase(true); //忽略大小写
    12. Example example = Example.of(user,matcher);
    13. List userList = userRepository.findAll(example);
    14. userList.forEach(u -> {
    15. System.out.println(u);
    16. });
    17. }

    11、分页排序加模糊查询

    1. //分页排序加模糊查询
    2. @Test
    3. public void test11(){
    4. Sort sort = Sort.by(Sort.Direction.DESC, "age");
    5. //page=0表示第一页
    6. PageRequest pageable = PageRequest.of(0, 4,sort);
    7. //模糊查询
    8. ExampleMatcher matcher = ExampleMatcher.matching()
    9. .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
    10. .withIgnoreCase(true);
    11. User user = new User();
    12. user.setName("est");
    13. Example example = Example.of(user, matcher);
    14. Page pages = userRepository.findAll(example, pageable);
    15. List userList = pages.getContent();
    16. userList.forEach(u -> {
    17. System.out.println(u);
    18. });
    19. }

    SpringData方法规范

    接口中,你可以自定义方法,但是需要满足一定的规则

    查询方法以 find 、read 、get 开头, 涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性以首字母大写。

    如:根据name模糊删除

    根据name或age等值删除

  • 相关阅读:
    MySQL高级:函数(一)系统函数
    SpringBoot整合Quartz示例
    多线程概述
    ffmpeg 通过遍历视频流,对视频帧进行打标
    刷算法Leetcode---8(二叉树篇)(层序遍历)
    运行vite项目报错:await import(‘source-map-support‘).then((r) => r.default.install())
    Flutter GetX使用详解
    GBase8s jdbc连接超时参数说明
    使用Netty进行协议开发:多协议支持与自定义协议的实现
    在Windows中自动压缩备份文件和目录的脚本
  • 原文地址:https://blog.csdn.net/m0_56799642/article/details/126232854