SpringBoot整合 EasyES (八)

news2024/10/7 8:28:44

一直在坑自己家人,对,说的就是你,大A.

上一章简单介绍了SpringBoot整合ES 实现简单项目(七), 如果没有看过,请观看上一章

Mybatis 有增强性的 MybatisPlus, ES 有增强性的吗? 有的, easy-es

​ Easy-Es(简称EE)是一款基于ElasticSearch(简称Es)官方提供的RestHighLevelClient打造的ORM开发框架,
在 RestHighLevelClient 的基础上,只做增强不做改变,为简化开发、提高效率而生,
您如果有用过Mybatis-Plus(简称MP),那么您基本可以零学习成本直接上手EE,EE是MP的Es平替版,
在有些方面甚至比MP更简单,同时也融入了更多Es独有的功能,助力您快速实现各种场景的开发.

​ 官网地址: https://www.easy-es.cn/pages/v1.x/1cebb8/

EE的主要特性如下:

  • 全自动索引托管:开发者无需关心索引的创建、更新及数据迁移等繁琐步骤,框架能自动完成。
  • 屏蔽语言差异:开发者只需要会MySQL的语法即可使用ES。
  • 代码量极少:与直接使用官方提供的RestHighLevelClient相比,相同的查询平均可以节省3-5倍的代码量。
  • 零魔法值:字段名称直接从实体中获取,无需手写。
  • 零额外学习成本: 开发者只要会国内最受欢迎的Mybatis-Plus用法,即可无缝迁移至EE。

一. SpringBoot 整合 Easy-Es

一.一 添加依赖

一.一.一 去除 spring-boot-starter-web 携带的 es 版本

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.elasticsearch.client</groupId>
                    <artifactId>elasticsearch-rest-high-level-client</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.elasticsearch</groupId>
                    <artifactId>elasticsearch</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

一.一.二 添加 easy-es 和相应的依赖

<!--引入 spring-data-elasticsearch-->
        <dependency>
            <groupId>cn.easy-es</groupId>
            <artifactId>easy-es-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!--添加依赖-->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.14.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.14.0</version>
        </dependency>

一.二 easy-es 配置 application.yml

easy-es:
  enable: true
  banner: false
  address: localhost:9200
  # 一些其它的额外配置
  keep-alive-millis: 30000 # 心跳策略时间 单位:ms
  connect-timeout: 5000 # 连接超时时间 单位:ms
  socket-timeout: 600000 # 通信超时时间 单位:ms
  request-timeout: 5000 # 请求超时时间 单位:ms
  connection-request-timeout: 5000 # 连接请求超时时间 单位:ms
  max-conn-total: 100 # 最大连接数 单位:个
  max-conn-per-route: 100 # 最大连接路由数 单位:个
  global-config:
    process-index-mode: smoothly #索引处理模式,smoothly:平滑模式,默认开启此模式, not_smoothly:非平滑模式, manual:手动模式
    print-dsl: true # 开启控制台打印通过本框架生成的DSL语句,默认为开启,测试稳定后的生产环境建议关闭,以提升少量性能
    distributed: false # 当前项目是否分布式项目,默认为true,在非手动托管索引模式下,若为分布式项目则会获取分布式锁,非分布式项目只需synchronized锁.
    db-config:
      map-underscore-to-camel-case: false # 是否开启下划线转驼峰 默认为false
      table-prefix:  # 索引前缀,可用于区分环境  默认为空 用法和MP一样
      id-type: customize # id生成策略 customize为自定义,id值由用户生成,比如取MySQL中的数据id,如缺省此项配置,则id默认策略为es自动生成
      field-strategy: not_empty # 字段更新策略 默认为not_null
      refresh-policy: immediate # 数据刷新策略,默认为不刷新
# 配置日志
logging:
  level:
    # # 开启trace级别日志,在开发时可以开启此配置,则控制台可以打印es全部请求信息及DSL语句,
    # 为了避免重复,开启此项配置后,可以将EE的print-dsl设置为false.
    tracer: trace

一.三 启动类配置扫描

使用 EsMapperScan 注解,进行配置扫描

@SpringBootApplication
@EsMapperScan("top.yueshushu.learn.esmapper")
public class EasyESApp {
    public static void main(String[] args) {
        SpringApplication.run(EasyESApp.class,args);
    }
}

一.四 配置实体 EsUser

@Data
@IndexName("es")
public class EsUser implements Serializable {
    // value 默认为 _id
    @IndexId(type = IdType.CUSTOMIZE)
    private Integer id;
    @IndexField(strategy = FieldStrategy.NOT_EMPTY, fieldType = FieldType.TEXT, analyzer = "ik_max_word")
    /**
     * 需要被高亮的字段
     */
    @HighLight(mappingField = "nameHighlightContent", preTag = "<font color='red'>", postTag = "</font>")
    private String name;
    @IndexField(strategy = FieldStrategy.NOT_EMPTY,fieldType = FieldType.TEXT, analyzer = "ik_max_word")
    private String nickName;
    @IndexField(fieldType = FieldType.INTEGER)
    private Integer age;
    @IndexField(fieldType = FieldType.KEYWORD_TEXT)
    private String sex;
    @Score
    private Float score;
    // 不存在
    @IndexField(exist = false)
    private String description;

    // 不存在
    @IndexField(exist = false)
    private Integer maxAge;
    @IndexField(exist = false)
    private Integer minAge;

    @IndexField(exist = false)
    private String nameHighlightContent;
}

使用一些配置注解 @IndexName @IndexId @IndexField

一.五 配置 Mapper

继承 BaseEsMapper 接口

public interface EsUserMapper extends BaseEsMapper<EsUser> {

}

这样,基本的配置就算是处理完成了, 后续 使用 EsUserMapper 即可以操作.

二. Easy-ES 配置项和注解

二.一 配置项

二.一.一 基础配置项

easy-es:
  enable: true # 是否开启EE自动配置
  address : 127.0.0.1:9200 # es连接地址+端口 格式必须为ip:port,如果是集群则可用逗号隔开
  schema: http # 默认为http
  username: elastic #如果无账号密码则可不配置此行
  password: 123456 #如果无账号密码则可不配置此行

二.一.二 扩展的连接池配置项

easy-es:
  keep-alive-millis: 18000 # 心跳策略时间 单位:ms
  connect-timeout: 5000 # 连接超时时间 单位:ms
  socket-timeout: 5000 # 通信超时时间 单位:ms 
  request-timeout: 5000 # 请求超时时间 单位:ms
  connection-request-timeout: 5000 # 连接请求超时时间 单位:ms
  max-conn-total: 100 # 最大连接数 单位:个
  max-conn-per-route: 100 # 最大连接路由数 单位:个

二.一.三 全局配置

类似于 mp 的配置处理

easy-es:
  banner: false # 默认为true 打印banner 若您不期望打印banner,可配置为false
  global-config:
    process-index-mode: smoothly #索引处理模式,smoothly:平滑模式,默认开启此模式, not_smoothly:非平滑模式, manual:手动模式
    print-dsl: true # 开启控制台打印通过本框架生成的DSL语句,默认为开启,测试稳定后的生产环境建议关闭,以提升少量性能
    distributed: false # 当前项目是否分布式项目,默认为true,在非手动托管索引模式下,若为分布式项目则会获取分布式锁,非分布式项目只需synchronized锁.
    async-process-index-blocking: true # 异步处理索引是否阻塞主线程 默认阻塞 数据量过大时调整为非阻塞异步进行 项目启动更快
    active-release-index-max-retry: 60 # 分布式环境下,平滑模式,当前客户端激活最新索引最大重试次数若数据量过大,重建索引数据迁移时间超过60*(180/60)=180分钟时,可调大此参数值,此参数值决定最大重试次数,超出此次数后仍未成功,则终止重试并记录异常日志
    active-release-index-fixed-delay: 180 # 分布式环境下,平滑模式,当前客户端激活最新索引最大重试次数 若数据量过大,重建索引数据迁移时间超过60*(180/60)=180分钟时,可调大此参数值 此参数值决定多久重试一次 单位:秒
    db-config:
      map-underscore-to-camel-case: false # 是否开启下划线转驼峰 默认为false
      table-prefix: daily_ # 索引前缀,可用于区分环境  默认为空 用法和MP一样
      id-type: customize # id生成策略 customize为自定义,id值由用户生成,比如取MySQL中的数据id,如缺省此项配置,则id默认策略为es自动生成
      field-strategy: not_empty # 字段更新策略 默认为not_null
      enable-track-total-hits: true # 默认开启,开启后查询所有匹配数据,若不开启,会导致无法获取数据总条数,其它功能不受影响,若查询数量突破1W条时,需要同步调整@IndexName注解中的maxResultWindow也大于1w,并重建索引后方可在后续查询中生效(不推荐,建议分页查询).
      refresh-policy: immediate # 数据刷新策略,默认为不刷新
      enable-must2-filter: false # 是否全局开启must查询类型转换为filter查询类型 默认为false不转换
      batch-update-threshold: 10000 # 批量更新阈值 默认值为1万

其中,主要的属性有 :

global-config.print-dsl: true
global-config.db-config.id-type: customize
global-config.db-config.field-strategy: not_empty
global-config.db-config.refresh-policy: immediate

  • id-type支持3种类型:
    • auto: 由ES自动生成,是默认的配置,无需您额外配置 推荐
    • uuid: 系统生成UUID,然后插入ES (不推荐)
    • customize: 用户自定义,在此类型下,用户可以将任意数据类型的id存入es作为es中的数据id,比如将mysql自增的id作为es的id,可以开启此模式,或通过@TableId(type)注解指定.
  • field-strategy支持3种类型:
    • not_null: 非Null判断,字段值为非Null时,才会被更新
    • not_empty: 非空判断,字段值为非空字符串时才会被更新
    • ignore: 忽略判断,无论字段值为什么,都会被更新
    • 在配置了全局策略后,您仍可以通过注解针对个别类进行个性化配置,全局配置的优先级是小于注解配置的
  • refresh-policy支持3种策略
    • none: 默认策略,不刷新数据
    • immediate : 立即刷新,会损耗较多性能,对数据实时性要求高的场景下适用
    • wait_until: 请求提交数据后,等待数据完成刷新(1s),再结束请求 性能损耗适中

二.一.四 日志配置

logging:
  level:
   tracer: trace # 开启trace级别日志

二.二 注解

二.二.一 mapper 扫描注解 @EsMapperScan

位置在Springboot启动类 ,功能与MP的@MapperScan一致

@SpringBootApplication
@EsMapperScan("top.yueshushu.learn.esmapper")
public class EasyESApp {
    public static void main(String[] args) {
        SpringApplication.run(EasyESApp.class,args);
    }
}

image-20230411142203035

二.二.二 索引名注解 @IndexName

使用位置, 在 实体类上

@Data
@IndexName("es")
public class EsUser implements Serializable {
    
}

image-20230411142311755

二.二.三 ES主键 @IndexId

使用位置:实体类中被作为ES主键的字段, 对应MP的@TableId注解

    // value 默认为 _id
    @IndexId(type = IdType.CUSTOMIZE)
    private Integer id;

image-20230411142421858

一般是用户自定义配置.

二.二.四 一般属性配置 @IndexField

实体类中被作为ES索引字段的字段

 @IndexField(strategy = FieldStrategy.NOT_EMPTY,fieldType = FieldType.TEXT, analyzer = "ik_max_word")
    private String nickName;
    @IndexField(fieldType = FieldType.INTEGER)
    private Integer age;

image-20230411142600105

二.二.五 得分注解 @Score

​ 实体类中被作为ES查询得分返回的字段

​ 比如需要知道本次匹配查询得分有多少时,可以在实体类中添加一个类型为Float/float的字段,并在该字段上添加@Score注解,在后续查询中,若es有返回当次查询的得分,则此得分会自动映射至此字段

    @Score
    private Float score;

二.二.六 高亮注解 @HighLight

配置高亮信息

    /**
     * 需要被高亮的字段
     */
    @HighLight(mappingField = "nameHighlightContent", preTag = "<font color='red'>", postTag = "</font>")
    private String name;
	
	@IndexField(exist = false)
    private String nameHighlightContent;

一般会配置一下 mappingField, 这样就不会修改之前的 name 属性了.

三. 基础的操作

跟 MybatisPlus 基本是一样的, 这里就不作过多的讲解了。

三.一 单个插入和批量插入

@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class BaseEsTest {
    @Resource
    private EsUserMapper esUserMapper;

    /**
    单个插入
     */
    @Test
    public void insertTest() {
        EsUser esUser = new EsUser();
        esUser.setId(1);
        esUser.setName("岳泽霖");
        esUser.setNickName("小泽霖");
        esUser.setAge(28);
        esUser.setSex("男");
        esUserMapper.insert(esUser);
    }
        /**
    批量插入
     */
    @Test
    public void batchInsertTest() {
        EsUser esUser = new EsUser();
        esUser.setId(2);
        esUser.setName("岳建立");
        esUser.setNickName("小建立");
        esUser.setAge(25);
        esUser.setSex("男");
        // 批量插入
        esUserMapper.insertBatch(Collections.singletonList(esUser));
    }
}
    

三.二 查询操作


    @Test
    public void getByIdTest() {
        EsUser esUser = esUserMapper.selectById(1);
        log.info(">> 查询用户: {}",esUser );
    }

    @Test
    public void selectAllTest() {
        List<EsUser> esUserList = esUserMapper.selectList(new LambdaEsQueryWrapper<>());
        esUserList.forEach(
                n->{
                    log.info("用户信息: {}",n);
                }
        );
    }
    /**
    根据id 批量查询
     */
    @Test
    public void getByIdsTest() {
        List<EsUser> esUserList = esUserMapper.selectBatchIds(Arrays.asList(1,2));
        esUserList.forEach(
                n->{
                    log.info("用户信息: {}",n);
                }
        );
    }
    /**
   查询数量
     */
    @Test
    public void countTest() {

        Long count = esUserMapper.selectCount(new LambdaEsQueryWrapper<>());
        log.info(">>> 总数是: {}", count);
    }

三.三 更新操作

    /**
     更新操作
     */
    @Test
    public void updateTest() {

        log.info(">>> 之前的数据是: {}" ,esUserMapper.selectById(1));

        EsUser esUser = esUserMapper.selectById(1);
        esUser.setAge(29);
        esUser.setNickName("两个蝴蝶飞");
        // 进行更新
        esUserMapper.updateById(esUser);

        log.info(">>> 修改后的数据是: {}" ,esUserMapper.selectById(1));
    }
    /**
        批量更新
     */
    @Test
    public void batchUpdateTest() {
        EsUser esUser = esUserMapper.selectById(1);
        esUser.setAge(30);
        esUser.setNickName("批量更新两个蝴蝶飞");

        esUserMapper.updateBatchByIds(Collections.singletonList(esUser));

        log.info(">>> 修改后的数据是: {}" ,esUserMapper.selectById(1));

    }
    /**
      根据条件进行更新
     */
    @Test
    public void updateByWrapperTest() throws Exception{
        LambdaEsUpdateWrapper<EsUser> esUserLambdaEsUpdateWrapper = new LambdaEsUpdateWrapper<>();
        esUserLambdaEsUpdateWrapper.le(EsUser::getAge,300);

        EsUser esUser = new EsUser();
        esUser.setNickName("根据条件更新2");
        esUser.setAge(33);
        esUserMapper.update(esUser,esUserLambdaEsUpdateWrapper);
        selectAllTest();

    }

三.四 删除操作

@Test
    public void deleteByIdTest() {
        // 根据id 进行删除
        esUserMapper.deleteById(1);
    }
    /**
     根据id 批量删除
     */
    @Test
    public void deleteBatchTest() {
        esUserMapper.deleteBatchIds(Collections.singletonList(2));
    }

    /**
    根据条件批量删除
     */
    @Test
    public void deleteByWrapperTest() throws Exception{
        LambdaEsQueryWrapper<EsUser> esUserLambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        esUserLambdaEsQueryWrapper.le(EsUser::getAge,300);

        esUserMapper.delete(esUserLambdaEsQueryWrapper);

        TimeUnit.SECONDS.sleep(2);
        selectAllTest();

    }

四. 查询操作

查询使用到 LambdaEsQueryWrapper 对象

方法基本与 mybatiplus 一致

MysqlEasy-ESes-DSL/es java api
andandmust
ororshould
=eqterm
!=neboolQueryBuilder.mustNot(queryBuilder)
>gtQueryBuilders.rangeQuery(‘es field’).gt()
>=ge.rangeQuery(‘es field’).gte()
<lt.rangeQuery(‘es field’).lt()
<=le.rangeQuery(‘es field’).lte()
like ‘%field%’likeQueryBuilders.wildcardQuery(field,value)
not like ‘%field%’notLikemust not wildcardQuery(field,value)
like ‘%field’likeLeftQueryBuilders.wildcardQuery(field,*value)
like ‘field%’likeRightQueryBuilders.wildcardQuery(field,value*)
betweenbetweenQueryBuilders.rangeQuery(‘es field’).from(xx).to(xx)
notBetweennotBetweenmust not QueryBuilders.rangeQuery(‘es field’).from(xx).to(xx)
is nullisNullmust not QueryBuilders.existsQuery(field)
is notNullisNotNullQueryBuilders.existsQuery(field)
ininQueryBuilders.termsQuery(" xx es field", xx)
not innotInmust not QueryBuilders.termsQuery(" xx es field", xx)
group bygroupByAggregationBuilders.terms()
order byorderByfieldSortBuilder.order(ASC/DESC)
minminAggregationBuilders.min
maxmaxAggregationBuilders.max
avgavgAggregationBuilders.avg
sumsumAggregationBuilders.sum
order by xxx ascorderByAscfieldSortBuilder.order(SortOrder.ASC)
order by xxx descorderByDescfieldSortBuilder.order(SortOrder.DESC)
-matchmatchQuery
-matchPhraseQueryBuilders.matchPhraseQuery
-matchPrefixQueryBuilders.matchPhrasePrefixQuery
-queryStringQueryQueryBuilders.queryStringQuery
select *matchAllQueryQueryBuilders.matchAllQuery()
-highLightHighlightBuilder.Field

先批量添加, 提前准备好数据

@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class SearchTest {
    @Resource
    private EsUserMapper esUserMapper;

    @Resource
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void batchInsertTest() {
        EsUser esUser1 = new EsUser();
        esUser1.setId(1);
        esUser1.setName("岳泽霖");
        esUser1.setNickName("小泽霖");
        esUser1.setAge(28);
        esUser1.setSex("男");

        EsUser esUser2 = new EsUser();
        esUser2.setId(2);
        esUser2.setName("岳建立");
        esUser2.setNickName("小建立");
        esUser2.setAge(26);
        esUser2.setSex("男");

        EsUser esUser3 = new EsUser();
        esUser3.setId(3);
        esUser3.setName("张三");
        esUser3.setNickName("张三");
        esUser3.setAge(24);
        esUser3.setSex("男");


        EsUser esUser4 = new EsUser();
        esUser4.setId(4);
        esUser4.setName("李四");
        esUser4.setNickName("李四");
        esUser4.setAge(24);
        esUser4.setSex("女");

        EsUser esUser5 = new EsUser();
        esUser5.setId(5);
        esUser5.setName("王二");
        esUser5.setNickName("王二");
        esUser5.setAge(16);
        esUser5.setSex("女");

        List<EsUser> userList = new ArrayList<>();
        userList.add(esUser1);
        userList.add(esUser2);
        userList.add(esUser3);
        userList.add(esUser4);
        userList.add(esUser5);
        esUserMapper.insertBatch(userList);
    }
}

只列举信息

四.一 equals

@Test
    public void equalsTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
       //  String name = "岳泽霖";
        String name = "霖";
        lambdaEsQueryWrapper.eq(StringUtils.hasText(name), EsUser::getName,name);
        List<EsUser> esUserList = esUserMapper.selectList(lambdaEsQueryWrapper);
        printInfo(esUserList);
    }

 public void printInfo( List<EsUser> esUserList) {
        if (CollectionUtils.isEmpty(esUserList)){
            log.info(">>>> 未查询出用户信息");
            return ;
        }
        esUserList.forEach(
                n->{
                    log.info("用户信息: {}" ,n);
                }
        );
    }

image-20230411144634744

四.二 and 组合

    @Test
    public void andTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        String name = "霖";
        String sex = "男";
        lambdaEsQueryWrapper.eq(StringUtils.hasText(name), EsUser::getName,name);
        lambdaEsQueryWrapper.eq(StringUtils.hasText(sex), EsUser::getSex,sex);
        List<EsUser> esUserList = esUserMapper.selectList(lambdaEsQueryWrapper);
        printInfo(esUserList);
    }

image-20230411144711211

四.三 or 组合

    @Test
    public void orTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        String name = "霖";
        String sex = "男";
        lambdaEsQueryWrapper.eq(StringUtils.hasText(name), EsUser::getName,name);
        lambdaEsQueryWrapper.or().eq(StringUtils.hasText(sex), EsUser::getSex,sex);
        List<EsUser> esUserList = esUserMapper.selectList(lambdaEsQueryWrapper);
        printInfo(esUserList);
    }

image-20230411144741250

四.四 配置原始 restHighLevelClient 查询


 @Resource
    private RestHighLevelClient restHighLevelClient;

    /**
        原先查询
     */
    @Test
    public void originTest() throws Exception{
        SearchRequest searchRequest = new SearchRequest();
        // 设置索引
        searchRequest.indices("es");

        /**
         构建条件
         */
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchRequest.source(searchSourceBuilder);

        // 进行请求
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits result = searchResponse.getHits();
        log.info(">>> 花费的时间:{}", searchResponse.getTook());
        log.info(">>>是否超时:{}", searchResponse.isTimedOut());
        log.info(">>>> 总的数量:{}", result.getTotalHits());
        log.info(">>>>最大的匹配分数值:{}", result.getMaxScore());
        log.info(">>>>查询结果输出开始");
        Arrays.stream(result.getHits()).forEach(
                n -> log.info(">>>获取内容:{}", n.getSourceAsString())
        );
        log.info(">>>> 查询结果输出结束");
    }


四.五 分页查询

    /**
    分页查询
     */
    @Test
    public void pageTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        EsPageInfo<EsUser> esUserPageInfo = esUserMapper.pageQuery(lambdaEsQueryWrapper, 1, 2);
        log.info(">>> 总数是: {}" ,esUserPageInfo.getTotal());
        printInfo(esUserPageInfo.getList());
    }

image-20230411144859974

四.六 排序

    /**
     排序查询
     */
    @Test
    public void orderTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        // 进行排序
        lambdaEsQueryWrapper.orderByDesc(EsUser::getId);
        EsPageInfo<EsUser> esUserPageInfo = esUserMapper.pageQuery(lambdaEsQueryWrapper, 1, 5);
        log.info(">>> 总数是: {}" ,esUserPageInfo.getTotal());
        printInfo(esUserPageInfo.getList());
    }

image-20230411144941905

四.七 获取 Dsl 数据

    /**
      获取 Dsl 数据
     */
    @Test
    public void getDslTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        // 进行排序
        lambdaEsQueryWrapper.orderByDesc(EsUser::getId);
        // from size
        lambdaEsQueryWrapper.limit((1-1) * 5,5);

        String source = esUserMapper.getSource(lambdaEsQueryWrapper);

        log.info(">>> 执行语句: {}", source);
    }

image-20230411145020903

四.八 查询部分字段

四.八.一 只查询部分字段

    /**
    只查询字段
     */
    @Test
    public void selectTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        String name = "霖";
        String sex = "男";
        lambdaEsQueryWrapper.eq(StringUtils.hasText(name), EsUser::getName,name);
        lambdaEsQueryWrapper.eq(StringUtils.hasText(sex), EsUser::getSex,sex);

        lambdaEsQueryWrapper.select(EsUser::getId,EsUser::getName);

        List<EsUser> esUserList = esUserMapper.selectList(lambdaEsQueryWrapper);
        printInfo(esUserList);
    }

image-20230411145104756

四.八.二 不查询某些字段

    /**
   不查询字段
     */
    @Test
    public void notSelectTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        String name = "霖";
        String sex = "男";
        lambdaEsQueryWrapper.eq(StringUtils.hasText(name), EsUser::getName,name);
        lambdaEsQueryWrapper.eq(StringUtils.hasText(sex), EsUser::getSex,sex);

        lambdaEsQueryWrapper.notSelect(EsUser::getId,EsUser::getAge);

        List<EsUser> esUserList = esUserMapper.selectList(lambdaEsQueryWrapper);
        printInfo(esUserList);
    }

image-20230411145144029

四.九 单字段去重

    /**
     单字段去重
     */
    @Test
    public void dictTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        lambdaEsQueryWrapper.distinct(EsUser::getAge);
        List<EsUser> esUserList = esUserMapper.selectList(lambdaEsQueryWrapper);
        printInfo(esUserList);
    }

image-20230411145241213

只查询出来四条记录

四.十 分组查询

    @Test
    public void groupTest() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        lambdaEsQueryWrapper.groupBy(EsUser::getAge);
        SearchResponse searchResponse = esUserMapper.search(lambdaEsQueryWrapper);
        log.info(">>> 查询数据: {}" ,searchResponse);
    }

image-20230411145342074

配置最大,最小

  @Test
    public void group2Test() {
        LambdaEsQueryWrapper<EsUser> lambdaEsQueryWrapper = new LambdaEsQueryWrapper<>();
        lambdaEsQueryWrapper.groupBy(EsUser::getAge);
        lambdaEsQueryWrapper.max(EsUser::getMaxAge);
        lambdaEsQueryWrapper.min(EsUser::getMinAge);
        SearchResponse searchResponse = esUserMapper.search(lambdaEsQueryWrapper);
        log.info(">>> 查询数据: {}" ,searchResponse);
    }

image-20230411145438843


本章节的代码放置在 github 上:

https://github.com/yuejianli/springboot/tree/develop/SpringBoot_EasyES

谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/425671.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java捕获编译时异常exception和运行时错误error的方法

背景 最近使用jacob的时候&#xff0c;由于编译没问题&#xff0c;运行时报如下&#xff0c;我 查看代码发现是调用jacob文件时&#xff0c;是下面的方法报错&#xff0c; ComThread.Release(); 这个方法编译不报错&#xff0c;是因为doCoUninitialize使用native修饰的&#…

java 通过 spring 官网创建springboot项目

文章java简单一写一个springboot入门案例带大家用idea工具工具创建了一个springboot简单的小案例 但有时 我们idea如果连不上网 就会有点问题 我们可以采用另一种创建方式 但这里的前提肯定就是 你的计算机是要有网的 然后访问 https://spring.io/ 打开spring的官网 在 Project…

去了字节跳动,才知道年薪40W的测试有这么多?

今年大环境不好&#xff0c;内卷的厉害&#xff0c;薪资待遇好的工作机会更是难得。最近脉脉职言区有一条讨论火了&#xff1a; 哪家互联网公司薪资最‘厉害’&#xff1f; 下面的评论多为字节跳动&#xff0c;还炸出了很多年薪40W的测试工程师 我只想问一句&#xff0c;现在的…

数据结构进阶:前缀和与差分

数据结构进阶&#xff1a;前缀和与差分基础前缀和基础差分区间乘积前缀置换经典差分性质题目前缀和变种高次前缀和高维前缀和 (SOSDP)蓝桥杯已经结束&#xff0c;打下来很难受。自己对于算法的掌握还是不够&#xff0c;遂继续开启博客书写&#xff0c;激励自己学习。本系列文章…

FinClip 云开发实践(附小程序demo)

在开发一个小程序时&#xff0c;除了考虑界面功能逻辑外&#xff0c;还需要后端的数据支持&#xff0c;开发者需要提前考虑服务器、存储和数据库等相关需求的支持能力&#xff0c;此外还可能需要花费时间精力在部署应用、和依赖服务的建设上。 ​ 因此&#xff0c;腾讯小程序为…

【Java】类和对象详解

1. 类和对象 1.1 类和对象的理解 客观存在的事物皆为对象 &#xff0c;所以我们也常常说万物皆对象。 类 类的理解 类是对现实生活中一类具有共同属性和行为的事物的抽象类是对象的数据类型&#xff0c;类是具有相同属性和行为的一组对象的集合简单理解&#xff1a;类就是对…

Dva.js(基础、简单例子解读)

简单介绍一下 近期在做react项目时&#xff0c;看到项目中数据的公共存储用的Dva.js&#xff0c;整体的代码结构看起来和vuex差不多&#xff0c;这两天趁着刚忙完&#xff0c;利用工作之余的时间空隙&#xff0c;大致了解了dva的基础理论&#xff0c;代码结构应用&#xff0c;参…

Qt 项目A调用项目B方法(项目架构管理)

前言 项目开发中&#xff0c;如果项目比较大&#xff0c;大多采用多项目的方式&#xff0c;主要是为了方便代码管理&#xff0c;也更开发变得更加方便。操作如下&#xff1a; 注&#xff1a;我用的版本是Qt 5.12.3 一、建立项目目录 要求&#xff1a; 1、项目A为主&#xff…

FreeRTOS中的任务与任务切换(笔记)

目录任务的定义栈和任务栈任务控制块任务初始化函数初始化任务栈任务创建函数pxTopOfStack任务列表初始化将任务插入到就绪列表中调度器xPortStartScheduler() 函数prvStartFirstTask()函数 &#xff08;该函数是偏硬件底层的函数&#xff0c;用汇编语言编写&#xff0c;在port…

中电金信「财务公司核心系统白皮书」正式发布!

随着数字技术的深度应用&#xff0c;数字化转型正迎来新一轮变革。如何促进企业战略转型&#xff0c;助力企业发展提质增效&#xff0c;以标准化、数字化、精细化支撑企业实现高质量发展&#xff0c;已成为财务公司数字化转型的重要课题。 为推进财务公司数字化转型工作要求&a…

恢复照片软件推荐,照片恢复就这么做!

案例&#xff1a;好用的恢复照片软件 【作为一名摄影博主&#xff0c;我每天拍的照片太多了&#xff0c;在筛选的时候总是容易错删重要的照片&#xff0c;大家有什么比较好的照片恢复软件或方法可以推荐吗&#xff1f;万分期待!】 随着数字化时代的发展&#xff0c;人们越来越…

QPixmap存在的坑,内存泄漏

QPixmap加载图片的时候&#xff0c;会把图片数据加入到QPixmapCache缓冲区上 如果多次加载&#xff0c;那么内存会被吃掉越来越多 本意QPixmap是用于显示需要比较快的地方&#xff0c;和硬件关联 QPixmap变量之间的赋值&#xff0c;并不会构造新的图片数据内存&#xff0c;而…

基于Eclipse下使用arm gcc开发GD32调用printf

系列目录 第一章 xxx 目录 系列目录 文章目录 文章目录 系列文章目录前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结前言 开发环境&#xff1a;Eclipse代替Keil&#xff0c;IAR 开发平台&#xff1a;GD32 开发编译器&#xff1a;arm-none-eabi- …

Adobe Acrobat Pro DC 2022的系统要求

Adobe Acrobat Pro DC 2022是一款功能强大的PDF编辑和管理软件。它可以帮助用户创建、编辑、转换、签署和共享PDF文档&#xff0c;并提供了多种工具和功能来优化文档的可访问性、安全性和可靠性。 Adobe Acrobat Pro DC 2022功能特色&#xff1a; 创建和编辑PDF文档&#xff1…

《低代码PaaS驱动集团企业数字化创新白皮书》-大型集团企业的数字化困局

大型集团企业的数字化困局 现状 /态势&#xff1a;数字化发展动力&#xff0c;构建数字化竞争力&#xff0c;实现敏捷的运营、治理、决策、体验 数字化转型大势所趋 全球化地缘政治紧张局势&#xff0c;供应链、通货膨胀、劳动力短缺以及新冠疫情全球大流行更增加了人们对全球…

HLS_OPENCV库的安装

借此机会来记录一下OPENCV库的安装:   首先需要知道的是说起OPENCV库有两种&#xff0c;一种是OPENCV库&#xff0c;还有一种是Xilinx官方自己的OPENCV库&#xff0c;前者可以用来在HLS中进行仿真&#xff0c;无法进行综合&#xff0c;而后者则是可以进行综合的。现将两种库的…

【综述型论文】图神经网络总结

文章目录图神经网络基于模型结构分类的图神经网络1. 循环图神经网络&#xff08;ResGNNs&#xff09;2. 卷积图神经网络基于谱域的ConvGNNs&#xff08;Spectral-based ConvGNNs&#xff09;基于空域的ConvGNNs&#xff08;Spatial-based ConvGNNs&#xff09;谱域图卷积模型和…

Python遥感开发之FY的批量处理

Python遥感开发之FY的批量处理0 FY遥感数据1 批量提取数据2 批量拼接TIF数据3 批量HAM转WGS投影&#xff08;重要&#xff09;4 批量掩膜裁剪介绍FY数据的格式&#xff0c;以及FY数据的批量提取数据、批量拼接数据、批量投影转换、批量掩膜裁剪等操作。本博客代码参考《 Hammer…

MySQL SQL优化 【建议熟读并背诵】

插入数据 批量插入数据 insert into tb_test values(1,Tom),(2,Cat),(3,Jerry);手动控制事务 start transaction; insert into tb_test values(1,Tom),(2,Cat),(3,Jerry); insert into tb_test values(4,Tom),(5,Cat),(6,Jerry); insert into tb_test values(7,Tom),(8,Cat…

在Windows中使用Linux命令安装这款软件就可以

由于平时经常使用Linux命令&#xff0c;所以导致在Windows的cmd中输入命令的时候经常打错&#xff0c;提示不是内部或外部命令&#xff0c;也不是可运行的程序。 那么有办法将补全cmd命令&#xff0c;使Linux中的命令在Windows中也能使用呢&#xff1f; 下面我来讲解如何在Win…