11、MongoDB--通过SpringBoot整合Spring Data MongoDB操作MongoDB数据库(反应式(异步)编程演示: 方法名关键字查询、@Query查询、自定义查询、样本查询)

目录

整合 Spring Data MongoDB 操作 MongoDB 数据库

演示前提:


登录单机模式的 mongodb 服务器命令

mongod.exe --config "E:\install\mongodb\mongodb-4.2.25\mongod.conf"

在这里插入图片描述


登录【test】数据库的 mongodb 客户端命令

mongo mongodb://192.168.0.107:27017/test -u LJHAAA -p 123456

在这里插入图片描述


登录【admin】数据库的 mongodb 客户端命令

mongo mongodb://192.168.0.107:27017/admin -u admin -p 123456

在这里插入图片描述


Spring Data MongoDB

DAO 接口只需继承 CrudRepositoryReactiveCrudRepository ,Spring Data MongoDB 就能为 DAO 组件提供实现类。

Spring Data MongoDB 支持方法名关键字查询(全自动)。

Spring Data MongoDB支持用@Query定义查询语句(半自动),
只不过该 @Query 注解是 Spring Data MongoDB 提供的。

Spring Data MongoDB 同样支持 DAO 组件添加自定义的查询方法(手动)
——通过添加额外的父接口,并为额外的该接口提供实现类,Spring Data MongoDB 就能该实现类中的方法“移植”到DAO组件中。

Spring Data MongoDB 同样支持 Example 样本查询。


MongoTemplate 和 CrudRepository 的区别

MongoTemplate详细介绍

在这里插入图片描述


方法名关键字查询(全自动)

MongoDB 有自己的查询语法,因此 Spring Data MongoDB 支持的方法名关键字同样非常强大。
——这些方法名关键字都会转换成对应的查询操作符

关键字查询中涉及两个模糊查询的方法:Like 和 Regex,其中 Regex 执行正则表达式匹配的查询,这一点没有任何问题;
——但 Like 只是用普通的通配符,比如 * 可匹配任意个、任意字符。


@Query查询(半自动)

@Query("{name: {$regex: ?0}}")
Flux<Book> findByQuery2(String namePattern);

还有类似的如下注解:

@Aggregation: 该注解修饰的方法执行聚集操作。
MongoDB 集合提供 aggregate 方法,该方法需要一个 pipeline 的参数,该参数一个数组,每个数组元素是一次聚集运算。

@Aggregation: 同样需要 pipeline 属性,该属性完全等同于 pipeline 参数

@CountQuery: 该注解修饰的方法将只返回符合查询条件的文档的数量。
相当于将 count 属性设为 true 的 @Query

@DeleteQuery: 该注解修饰的方法将删除符合查询条件的文档。
相当于将 delete 属性设为 true 的 @Query

@ExistsQuery: 该注解修饰的方法将只返回是否包含符合查询条件的文档。
相当于将 exists 属性设为 true 的 @Query

@Query: 该注解修饰的方法将返回符合查询条件的文档。


自定义查询方法(全手动)

让 DAO 接口继承自定义 DAO 接口、并为自定义 DAO 接口提供实现类,可以为 DAO 组件添加自定义查询方法。Spring Data MongoDB 会将父接口的实现类中的查询方法移植到DAO组件中。

自定义查询方法既可用 MongoTemplate 执行查询,也可通过 MongoTemplate 的 execute() 方法调用 MongoDB 驱动的底层 API 执行查询。

【建议:】 Spring Data MongoDB 在定义数据类,建议使用 String 类型的 ID。

【问题:】 MongoDB 为什么没有支持自增长的主键?

MongoDB 和 MySQL、PgSQL 是不同,MongoDB 从开始就被设计成分布式环境的数据库,
——在分布式环境下使用自增长主键的性能相对是比较差的,因此 MongoDB 放弃了这种设计,改为使用 ObjectId 的主键。


方法名的开头关键字

在这里插入图片描述


方法名支持的关键字

在这里插入图片描述
在这里插入图片描述


Spring Data MongoDB的注解


Spring Data Mongo DB提供了如下注解:

@Document: 该注解指定将数据类映射到MongoDB的集合。

@MongoId: 映射标识属性。与@Id相比,该注解可指定标识属性的类型。

@Field: 该注解指定将数据类的属性映射到集合的字段。如果不使用该注解,默认基于同名映射原则。


Spring Data MongoDB 提供如下索引化注解:

@CompoundIndex和@CompoundIndexes: 用于指定对多个字段创建组合索引(也就是复合索引)。
其中@CompoundIndexes作为容器,为@CompoundIndex提供重复注解的支持。

@GeoSpatialIndexed: 指定对该属性使用MongoDB的地理空间索引功能创建索引。

@HashIndexed: 指定被注解修饰的属性应作为计算Hash索引的key。

@Indexed: 指定对普通类型的属性建立索引。
可指定 direction(1或1-1)、name、partialFilter、sparse、unique 正好对应于创建索引时可指定的选项。

@TextIndexed: 指定将字段作为全文检索索引的组成部分,MongoDB 的每个集合只能有一个全文检索索引,所有带 @TextIndexed 注解的字段都被合并到一个索引中。



代码演示


1、创建项目


勾选上同步和反应式的依赖

在这里插入图片描述


2、配置 MongoDB 连接


方式一:

Spring Boot 自动连接URL为 “mongodb://localhost/test” 的 MongoDB 服务器。
也可通过 spring.data.mongodb.uri 属性改变 MongoDB 服务器的 URL ,
例如通过如下属性指定 MongoDB 副本集的 URL :

   spring.data.mongodb.uri=mongodb://user:pass@host1:12345,host2:23456/boot

上面配置指定了两个副本:位于host1:12345 的副本和位于 host2:23456的副本。

一旦指定了 spring.data.mongodb.uri,那就无需指定 host, port, credentials,replica属性。

简单来说,uri 相当于是指定连接 MongoDB 的快捷方式。


查看 MongoProperties 这个属性配置类

在这里插入图片描述


方式二:用这个

也可通过如下方式配置 MongoDB 服务器的地址:

# 连接mongodb数据库

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=test
spring.data.mongodb.username=LJHAAA
spring.data.mongodb.password=123456

# 指定 spring.data.mongodb 根据实体类Book的字段上的索引注解(@Indexed、@TextIndexed )来创建索引
spring.data.mongodb.auto-index-creation=true

所有 spring.data.mongodb.* 开头的属性都由 MongoProperties 负责处理

在这里插入图片描述


3、添加 Book 实体类

在这里插入图片描述


4、添加 BookDao 接口


4-1: 方法名关键字查询的接口方法(全自动)

继承 ReactiveCrudRepository 接口,属于反应式编程,属于异步操作。
反应式编程是一种面向异步数据流的编程范式,其核心思想是通过观察者模式和函数式编程的方式处理数据流。

在这里插入图片描述


4-2: @Query查询的接口方法(半自动)

在这里插入图片描述


4-3: 自定义查询方法(全手动)

更新中~



5、基本的增删改查 – 测试类演示


5-1:往 books 集合添加一条文档,自己指定id值
代码

在这里插入图片描述


结果

成功往mongodb数据库里面的【books】集合添加了一条文档数据

在这里插入图片描述


Tree View 视图

在这里插入图片描述


Table View 视图

在这里插入图片描述


5-2:往 books 集合添加多条文档,由mongodb生成id值
代码

在这里插入图片描述


结果

在这里插入图片描述


在这里插入图片描述


5-3:根据 id 查询文档
代码

在这里插入图片描述


结果

在这里插入图片描述


5-4:根据 id 查询文档并修改该文档
代码

在这里插入图片描述


看每个方法调用的返回值

在这里插入图片描述


结果

在这里插入图片描述


5-5:根据 id 删除文档
代码

在这里插入图片描述


结果

id 为 1 的文档已经被删除了

在这里插入图片描述


6、方法名关键字查询(全自动查询)-- 测试类演示


6-1:根据名字查询文档
代码

在这里插入图片描述


结果

在这里插入图片描述


6-2:根据价格范围查询
代码

在这里插入图片描述


结果

在这里插入图片描述


6-3:根据【author】字段进行【通配符】查询
代码

在这里插入图片描述


结果

在这里插入图片描述


6-4:通过名字来进行正则表达式查询
代码

在这里插入图片描述


结果

在这里插入图片描述


6-5:查询价格大于指定参数值的文档有几条
代码

在这里插入图片描述


结果

在这里插入图片描述



7、@Query查询(半自动查询)-- 测试类演示


7-1:通过关键字对文档进行全文检索
代码

在这里插入图片描述


结果

在这里插入图片描述


7-2:通过 【作者】 和 【价格大于指定参数值】 来查询文档
代码

在这里插入图片描述


结果

在这里插入图片描述


8、自定义查询(全手动)-- 测试类演示


1、写一个 Dao 接口,自定义查询方法

在接口写上自己自定义的查询方法,然后作为父接口,让 BookDao 接口去继承。

在这里插入图片描述


2、自定义查询方法的实现类及测试类演示

2-1:要求书名【name】匹配这个这个正则表达式【nameRegex】,且价格【price】大于这个【startPrice】

自定义查询方法的实现类

在这里插入图片描述


测试代码

进行单元测试

在这里插入图片描述


测试结果

在这里插入图片描述


2-2:查询价格在这个范围的文档

自定义查询方法的实现类

在这里插入图片描述


测试代码

在这里插入图片描述


测试结果

在这里插入图片描述


9、样本查询 – 测试类演示


1、样本查询接口

这里的 DAO 接口已经继承了这个可以实现样本查询的接口了。

在这里插入图片描述


2、测试方法

在这里插入图片描述


3、测试结果

在这里插入图片描述



完整代码


Book 实体类

package cn.ljh.mongoboot.domain;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.index.TextIndexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.FieldType;
import org.springframework.data.mongodb.core.mapping.MongoId;

/**
 * author JH  2024-03
 */

//映射到mongodb数据库里面的【books】集合
@Document("books")
@Data
public class Book
{

    // id 的类型定义成String,灵活性比较大
    // @MongoId(FieldType.INT64)

    //普通的 @Id 注解更合适
    @Id
    private String id;

    //给【name】字段建立索引
    @Indexed
    private String name;

    @Indexed
    private double price;

    private String author;

    //表示 【desc】 字段映射到数据库集合中的【description】字段列
    @Field("description")
    @TextIndexed  //目前全文检索默认不支持中文
    private String desc;

    //无参构造器
    public Book(){}

    //有参构造器
    public Book( String name, double price, String author, String desc)
    {
        this.name = name;
        this.price = price;
        this.author = author;
        this.desc = desc;
    }
}


application.properties 配置类



# 连接mongodb数据库
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=test
spring.data.mongodb.username=LJHAAA
spring.data.mongodb.password=123456

# 指定 spring.data.mongodb 根据实体类Book的字段上的索引注解(@Indexed@TextIndexed )来创建索引
spring.data.mongodb.auto-index-creation=true
        

BookDao 方法名关键字查询和@Query查询的接口

package cn.ljh.mongoboot.dao;

import cn.ljh.mongoboot.domain.Book;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * author JH  2024-03
 */

//类型参数1:操作的实体类  ; 类型参数2:实体类的主键类型
public interface BookDao extends
        ReactiveCrudRepository<Book, String>,
        ReactiveQueryByExampleExecutor<Book>,
        CustomBookDao
{
    //===================================================方法名关键字查询(全自动)==========================================
    //返回值为 Flux ,表示接收多个返回值 ;  返回值为 Mono ,表示接收单个返回值

    //根据【关键字】,查询【name】字段包含该关键字的文档
    Flux<Book> findByName(String name);

    //根据【关键字】,对【price】字段的值进行范围查询
    Flux<Book> findByPriceBetween(double startPrice, double endPrice);

    //根据【关键字】,通过【通配符】形式查询【author】字段包含该关键字的文档
    Flux<Book> findByAuthorLike(String authorPattern);

    //根据【关键字】,通过【正则表达式】方式查询【name】字段包含该关键字的文档
    Flux<Book> findByNameRegex(String name);

    //查询【price】字段的值大于指定参数值(关键字)的文档【有几条】
    Mono<Integer> countByPriceGreaterThan(double startPrice);

    //===================================================@Query查询(半自动)==============================================

    //通过关键字 term 对文档进行全文检索
    @Query("{$text: {$search: ?0}}")
    Flux<Book> findByText(String term);


    //通过 【author】字段 和 【price】价格大于指定参数值 来查询文档
    @Query("{author: ?0 ,price:{$gt: ?1}}")
    Flux<Book> findByQuery(String author, double startPrice);



}



CustomBookDao 自定义查询方法的接口

package cn.ljh.mongoboot.dao;

import cn.ljh.mongoboot.domain.Book;
import reactor.core.publisher.Flux;

/**
 * author JH  2024-03
 */

//自定义查询方法的接口

public interface CustomBookDao
{

    //要求书名【name】匹配这个这个正则表达式【nameRegex】,且价格【price】大于这个【startPrice】
    Flux<Book> findByCustomRegexAndPrice(String nameRegex , double startPrice);

    //查询价格在这个范围的文档
    Flux<Book> findByCustomPrice(double startPrice , double endPrice);


}

CustomBookDaoImpl 自定义查询方法的实现类

package cn.ljh.mongoboot.dao.impl;

import cn.ljh.mongoboot.dao.CustomBookDao;
import cn.ljh.mongoboot.domain.Book;
import com.mongodb.BasicDBObject;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import reactor.core.publisher.Flux;

/**
 * author JH  2024-03
 */
public class CustomBookDaoImpl implements CustomBookDao
{
    @Autowired
    private ReactiveMongoTemplate mongoTemplate;

    @Override
    public Flux<Book> findByCustomRegexAndPrice(String nameRegex, double startPrice)
    {
        //Spring Data MongoDB 提供了一个 Criteria类 来构建 query 这个查询对象

        // where是Criteria类的一个静态方法,用于指定要查询的字段或属性
        // Criteria.where("name")表示对"name"字段进行查询操作,
        // .regex(nameRegex)表示使用正则表达式进行匹配,nameRegex是传入的名称的正则表达式
        // .and("price")表示在上述查询条件的基础上再加入"price"字段的查询条件
        // .gt(startPrice)表示查询大于给定起始价格的值

        Query query = Query.query(
                Criteria
                        .where("name").regex(nameRegex) //查询条件1
                        .and("price").gt(startPrice));  //查询条件2

        //query:代表查询条件 ; Book.class:要查询的实体对象
        Flux<Book> bookFlux = mongoTemplate.find(query, Book.class);

        return bookFlux;
    }






    @Override
    public Flux<Book> findByCustomPrice(double startPrice, double endPrice)
    {
        //.execute 方法用来执行一个MongoDB查询操作
        //mongoCollection,来自 MongoDB的驱动 API ,代表一个 collection

        Flux<Book> bookFlux = mongoTemplate.execute(Book.class, mongoCollection ->
        {
            //自定义的查询条件是这样的:{price: { $gt: startPrice , $lt:endPrice }}

            //这个BasicDBObject 就是代表查询条件中的一个对象
            BasicDBObject cond = new BasicDBObject();

            //给这个对象设置查询条件,就能得到这个 { $gt: startPrice , $lt:endPrice }
            cond.put("$gt", startPrice);
            cond.put("$lt", endPrice);

            //再创建一个对象
            BasicDBObject bson = new BasicDBObject();
            //再把查询条件设置进去,就得到这个 {price: { $gt: startPrice , $lt:endPrice }} 查询对象
            bson.put("price", cond);

            return Flux.from(mongoCollection.find(bson))
                    .map(document ->
                    {
                        Book book = new Book(
                                (String) document.get("name"),
                                (Double) document.get("price"),
                                (String) document.get("author"),
                                (String) document.get("description"));

                        //因为 id 有普通的string类型,也有 objectId 类型,所以需要做判断
                        Object id = document.get("_id");
                        //如果 id 是 ObjectId 类型; instanceof是Java中的一个运算符,用于检查一个对象是否属于某个特定的类型或其子类型
                        if (id instanceof ObjectId)
                        {
                            ObjectId obId = (ObjectId) id;
                            //toHexString是ObjectId类的一个方法,用于将ObjectId对象转换为十六进制字符串表示形式
                            book.setId(obId.toHexString());
                        } else
                        { book.setId((String) id); }
                        return book;
                    });
        });
        return bookFlux;
    }
}





BookDaoTest 测试类

package cn.ljh.mongoboot.dao;

import cn.ljh.mongoboot.domain.Book;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.repository.Query;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Optional;

/**
 * author JH  2024-03
 */

//表示不要用web环境来进行测试
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class BookDaoTest
{

    //依赖注入
    @Autowired
    private BookDao bookDao;


    //==============================================增删改查==============================================================


    //添加一个文档到books集合里面,该文档的id为自己指定的

    @ParameterizedTest //表示这个方法是一个参数化的测试
    //需要多个参数进行测试,用这个注解
    @CsvSource({
            //因为 mongodb 目前不支持中文进行全文检索,所以把内容写成英文来测试
            "1,火影忍者,100,岸本齐史,this cartoon is very good"
    })
    public void testSaveWithId(String id, String name, double price, String author, String desc)
    {

        Book b = new Book(name, price, author, desc);

        //自己设置id
        b.setId(id);

        Mono<Book> saveResult = bookDao.save(b);

        //使用同步方式测试反应式API
        //saveResult.block()是一个同步方法。在调用block()方法时,它会阻塞当前线程,直到saveResult的操作完成并返回结果
        Book book = saveResult.block();

        System.err.println(book);

    }


    //添加多个文档到books集合里面,该文档的id为mongodb自己指定的

    //表示这个方法是一个参数化的测试
    @ParameterizedTest
    //需要多个参数进行测试,用这个注解
    @CsvSource({
            "家庭教师,200,天野明,aa this cartoon is jiatingjiaoshi",
            "七龙珠,300,鸟山明,aa this cartoon is very qilongzhu",
            "蜡笔小新,400,臼井仪人,bb this cartoon is very labixiaoxin"
    })
    public void testSaveWithId(String name, double price, String author, String desc)
    {

        Book b = new Book(name, price, author, desc);

        Mono<Book> saveResult = bookDao.save(b);

        //使用同步方式测试反应式API
        //saveResult.block()是一个同步方法。在调用block()方法时,它会阻塞当前线程,直到saveResult的操作完成并返回结果
        Book book = saveResult.block();

        System.err.println(book);

    }


    //根据id查询文档
    @ParameterizedTest
    //测试方法只需要一个参数用这个注解
    @ValueSource(strings = {
            "1",
            "65eda80aec60bd4deae6f38b"
    })
    public void testFindById(String id)
    {
        Book block = bookDao.findById(id).block();

        System.err.println(block);

    }


    //对文档进行修改
    @Test
    public void testUpdate()
    {
        //bookDao.findById("1") 返回的是一个Mono<Book>类型的对象
        Mono<Book> bookMono = bookDao.findById("1");

        //blockOptional()是Mono类型的一个方法,它会阻塞当前线程并返回一个Optional对象。如果findById操作成功,Optional对象将包含查找到的图书对象;否则,Optional对象将为空
        Optional<Book> b = bookMono.blockOptional();

        //如果Optional对象中存在图书对象,则执行ifPresent中的逻辑
        b.ifPresent(
                //使用Lambda表达式的方式对查找到的图书进行操作
                book ->
                {
                    //进行修改操作
                    book.setName(book.getName() + "AAAAA");
                    //使用.block()方法阻塞当前线程,直到保存操作完成。这样确保更新操作在调用block()之前完成,并且等待操作结果返回
                    bookDao.save(book).block();
                }
        );
    }


    //根据id查询文档
    @ParameterizedTest
    //测试方法只需要一个参数用这个注解
    @ValueSource(strings = {
            "1",
    })
    public void testDeleteById(String id)
    {
        //因为反应式是异步操作,有可能出现删除操作还没完成,这个测试方法已经先一步执行完成了,所以导致删除失败
        //所以用.block()方法阻塞当前线程,直到删除操作完成,再继续执行这个测试方法
        bookDao.deleteById(id).block();

    }


    //==============================================方法名关键字查询(全自动查询)============================================

    //根据名字查询文档

    //表示这个方法是一个参数化的测试方法
    @ParameterizedTest
    //只需要一个参数用这个注解
    @ValueSource(strings = {
            "火影忍者",
            "七龙珠"
    })
    public void testFindByName(String name)
    {
        //反应式--异步操作
        Flux<Book> book = bookDao.findByName(name);

        //将Flux<Book>类型的对象转换为Iterable<Book>类型的对象,这样可以遍历处理异步操作的结果
        //Iterable是Java中的一个接口,用于表示可迭代的对象集合。
        Iterable<Book> books = book.toIterable();

        books.forEach(System.err::println);


    }


    //根据价格范围查询

    @ParameterizedTest
    @CsvSource({
            "50,250",
            "150,450"
    })
    public void testFindByPriceBetween(double startPrice, double endPrice)
    {

        Flux<Book> bookFlux = bookDao.findByPriceBetween(startPrice, endPrice);
        bookFlux.toIterable().forEach(System.err::println);

    }


    //根据【author】字段进行【通配符】查询
    @ParameterizedTest
    @ValueSource(strings = {
            "天*",
            "岸*"
    })
    public void testFindByAuthorLike(String authorPattern)
    {
        Flux<Book> bookFlux = bookDao.findByAuthorLike(authorPattern);
        bookFlux.toIterable().forEach(System.err::println);

    }


    //通过名字来进行正则表达式查询
    @ParameterizedTest
    @ValueSource(strings = {
            // ^ 符号表示开头,表示必须由【火】字开头; 这个 . 这个点表示匹配任意字符;  $ 符号表示结尾
            "^火.+$",
            //^ . 表示任意符号开头,中间包含【小】,后面的.表示任意符号结尾
            "^.+小.+$"
    })
    public void testFindByNameRegex(String name)
    {

        Flux<Book> bookFlux = bookDao.findByNameRegex(name);
        bookFlux.toIterable().forEach(System.err::println);

    }


    //查询价格大于指定参数值的文档有几条
    @ParameterizedTest
    @ValueSource(doubles = {
            100.0,
            200.0
    })
    public void testCountByPriceGreaterThan(double startPrice)
    {
        System.err.println("price 大于【 " + startPrice + " 】的文档有【 " + bookDao.countByPriceGreaterThan(startPrice).block() + " 】条");


    }


    //===================================================@Query查询(半自动)==============================================

    //通过关键字 term 对文档进行全文检索

    @ParameterizedTest
    @ValueSource(strings = {
            "good",
            "aa"
    })
    public void testFindByText(String term)
    {
        Flux<Book> bookFlux = bookDao.findByText(term);
        bookFlux.toIterable().forEach(System.err::println);

    }


    //通过 作者 和 价格大于指定参数值 来查询文档
    @ParameterizedTest
    @CsvSource({
            "天野明,50",
            "天野明,500"
    })
    public void testFindByQuery(String author, double startPrice)
    {
        Flux<Book> bookFlux = bookDao.findByQuery(author, startPrice);
        bookFlux.toIterable().forEach(System.err::println);

    }


    //==============================================自定义查询(全手动查询)=================================================


    //要求书名【name】匹配这个这个正则表达式【nameRegex】,且价格【price】大于这个【startPrice】


    @ParameterizedTest
    @CsvSource({
            //^ 表示开头 , 点 . 表示任意字符 ,$ 表示结尾 :全部就是以任意字符开头,然后中间有个【影】字,然后以任意字符结尾
            "^.+影.+$ , 50",
            "^.+教.+$, 50"
    })
    public void testFindByCustomRegexAndPrice(String nameRegex, double startPrice)
    {
        Flux<Book> bookFlux = bookDao.findByCustomRegexAndPrice(nameRegex, startPrice);
        bookFlux.toIterable().forEach(System.err::println);
    }





    //查询价格在这个范围的文档

    @ParameterizedTest
    @CsvSource({
            "99,199",
            "199,399"
    })
    public void testFindByCustomPrice(double startPrice, double endPrice)
    {
        Flux<Book> bookFlux = bookDao.findByCustomPrice(startPrice, endPrice);
        bookFlux.toIterable().forEach(System.err::println);

    }


    //==============================================样本查询=============================================================



    @ParameterizedTest
    @CsvSource({
            "火影忍者,岸本齐史",
            "家庭教师,天野明明明"
    })
    public void testByExanple(String name, String author)
    {

        //构建一个样本查询的对象
        Example<Book> example = Example.of(
                new Book(name, 0.0, author, null),
                ExampleMatcher.matching()
                        .withIgnoreNullValues() //忽略 null 属性
                        .withIgnorePaths("price") //忽略 price 属性
        );

        Flux<Book> bookFlux = bookDao.findAll(example);
        Iterable<Book> books = bookFlux.toIterable();
        books.forEach(System.err::println);
    }




}

pom.xml 依赖文档

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>

    <groupId>cn.ljh</groupId>
    <artifactId>mongoboot</artifactId>
    <version>1.0.0</version>
    <name>mongoboot</name>


    <properties>
        <java.version>11</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>


    <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-data-mongodb-reactive</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

  • 41
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_L_J_H_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值