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、添加依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-mongodb</artifactId>
       </dependency>
    </dependencies>

2、配置文件配置

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

3、准备一个实体类User

//@Document映射到哪一个集合
@Data
@Document("User")
public class User {
    @Id
    private String id;
    private String name;
    private Integer age;
    private String email;
    private String createDate;
}

MongoTemplate方法测试

常用方法
mongoTemplate.findAll(User.class): 查询User文档的全部数据
mongoTemplate.findById(<id>, 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;
@SpringBootTest
public class MDTest {

    @Autowired
    private MongoTemplate mongoTemplate;

}

1、insert 添加

    //添加
    @Test
    public void test1() {
        User user = new User();
        user.setAge(19);
        user.setName("阿肥");
        user.setEmail("422eeeee@qq.com");
        user.setCreateDate("2022-08-09");
        //主键id会自动回填
        mongoTemplate.insert(user);

        System.out.println(user);
    }


2、updateMulti 修改

    //修改
    @Test
    public void test8(){
        Query query = new Query(Criteria.where("name").is("阿广"));

        Update update = new Update();
        update.set("name","test3");
        update.set("age",18);
        //修改符合条件的多列
        UpdateResult updateResult = mongoTemplate.updateMulti(query, update, User.class);
    }


3、save修改

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


4、remove带条件删除

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


5、查询所有

    //查询所有
    @Test
    public void test2() {
        List<User> userList = mongoTemplate.findAll(User.class);
        userList.forEach(u -> {
            System.out.println(u);
        });
    }


6、根据id查询

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


7、根据条件查询

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


8、模糊查询

    //模糊查询
    @Test
    public void test5() {
        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);
        userList.forEach(u -> {
            System.out.println(u);
        });
    }


9、分页查询

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


10、带条件的分页查询

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

11、mongoTemplate做聚合查询

要做到页面效果:

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

    @Override
    public Map<String, Object> getRuleSchedule(long page, long limit, String hoscode, String depcode) {
        //1.定义查询条件
        Criteria criteria = Criteria.where("hoscode").is(hoscode).and("depcode").is(depcode);
        //2.定义聚合
        Aggregation aggre = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("workDate")
                        .first("workDate").as("workDate")
                        .sum("reservedNumber").as("reservedNumber")
                        .sum("availableNumber").as("availableNumber")
                        .count().as("docCount"),
                Aggregation.sort(Sort.Direction.ASC, "workDate"),
                Aggregation.skip((page - 1) * limit),
                Aggregation.limit(limit)
        );
        //执行查询
        AggregationResults<BookingScheduleRuleVo> aggregate1 = mongoTemplate.aggregate(aggre, Schedule.class, BookingScheduleRuleVo.class);
        List<BookingScheduleRuleVo> bookingScheduleRuleVoList = aggregate1.getMappedResults();

        //3.获取总记录数
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("workDate")
        );
        AggregationResults<BookingScheduleRuleVo> aggregate = mongoTemplate.aggregate(aggregation, Schedule.class, BookingScheduleRuleVo.class);
        int total = aggregate.getMappedResults().size();

        //4. 获取日期对应的星期
        for (BookingScheduleRuleVo bookingScheduleRuleVo : bookingScheduleRuleVoList) {
            Date workDate = bookingScheduleRuleVo.getWorkDate();
            String dayOfWeek = this.getDayOfWeek(new DateTime(workDate));
            bookingScheduleRuleVo.setDayOfWeek(dayOfWeek);
        }

        //5.获取医院名称
        String hosname = hospitalService.getByHoscode(hoscode).getHosname();
        Map<String, String> baseMap = new HashMap<>();
        baseMap.put("hosname", hosname);
        //6. 封装返回值
        Map<String, Object> result = new HashMap<>();
        result.put("bookingScheduleRuleList", bookingScheduleRuleVoList);
        result.put("total", total);
        result.put("baseMap", baseMap);
        return result;
    }

    /**
     * 根据日期获取星期数据
     *
     * @param dateTime
     * @return
     */
    private String getDayOfWeek(DateTime dateTime) {
        int dayOfWeek = dateTime.getDayOfWeek();
        List<String> strings = Arrays.asList("周一", "周二", "周三", "周四", "周五", "周六", "周日");
        return strings.get(dayOfWeek - 1);
    }

 最主要的点:

断点:执行查询的效果


 MongoRepository

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

添加一个接口:

@Repository
public interface UserRepository extends MongoRepository<User,String> {
}

测试前提:

@SpringBootTest
public class RepositoryMDTest {

    @Autowired
    private UserRepository userRepository;

}

1、添加

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

2、修改

    //修改
    @Test
    public void test2() {
        User user = userRepository.findById("62f075ef7843a4005c1c4abe").get();
        user.setName("通仔");
        user.setAge(26);
        User save = userRepository.save(user);
        System.out.println(save);
    }

3、查询所有

    //查询所有
    @Test
    public void test3() {
        List<User> userList = userRepository.findAll();
        System.out.println(userList);
    }

4、根据id查询

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

5、根据id删除

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

6、查询所有并排序

    //查询所有并排序
    @Test
    public void test6(){
        Sort sort = Sort.by(Sort.Direction.DESC, "age");
        List<User> userList = userRepository.findAll(sort);
        userList.forEach(user -> {
            System.out.println(user);
        });
    }

7、条件查询

    //条件查询
    @Test
    public void test7(){
        User user = new User();
        user.setName("阿广");
        Example<User> userExample = Example.of(user);
        List<User> userList = userRepository.findAll(userExample);
        userList.forEach(u -> {
            System.out.println(u);
        });
    }

8、分页查询

    //分页查询
    @Test
    public void test8(){
        //page=0表示第一页
        PageRequest pageable = PageRequest.of(0, 2);
        Page<User> all = userRepository.findAll(pageable);
        List<User> userList = all.getContent();
        userList.forEach(u -> {
            System.out.println(u);
        });
        long totalElements = all.getTotalElements();//总记录数
        int totalPages = all.getTotalPages();//总页数
        System.out.println("总记录数:"+ totalElements);
        System.out.println("总页数:"+ totalPages);
    }

9、分页查询并排序

    //分页排序写在一块
    @Test
    public void test9(){
        Sort sort = Sort.by(Sort.Direction.DESC, "age");
        //page=0表示第一页
        PageRequest pageable = PageRequest.of(0, 2,sort);
        Page<User> all = userRepository.findAll(pageable);
        List<User> userList = all.getContent();
        userList.forEach(u -> {
            System.out.println(u);
        });
        long totalElements = all.getTotalElements();//总记录数
        int totalPages = all.getTotalPages();//总页数
        System.out.println("总记录数:"+ totalElements);
        System.out.println("总页数:"+ totalPages);
    }

10、模糊查询

    //模糊查询
    @Test
    public void test10(){
        User user = new User();
        user.setName("test");

        //模糊查询固定格式
        ExampleMatcher matcher =
                ExampleMatcher
                        .matching()
                        .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)//模糊查询
                        .withIgnoreCase(true); //忽略大小写

        Example<User> example =  Example.of(user,matcher);

        List<User> userList = userRepository.findAll(example);
        userList.forEach(u -> {
            System.out.println(u);
        });
    }

11、分页排序加模糊查询

    //分页排序加模糊查询
    @Test
    public void test11(){
        Sort sort = Sort.by(Sort.Direction.DESC, "age");
        //page=0表示第一页
        PageRequest pageable = PageRequest.of(0, 4,sort);

        //模糊查询
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
                .withIgnoreCase(true);

        User user = new User();
        user.setName("est");

        Example<User> example = Example.of(user, matcher);

        Page<User> pages = userRepository.findAll(example, pageable);

        List<User> userList = pages.getContent();
        userList.forEach(u -> {
            System.out.println(u);
        });
    }

SpringData方法规范

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

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

如:根据name模糊删除

根据name或age等值删除

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值