Easy-Es:像mybatis-plus一样,轻松操作ES

0. 引言

es的java客户端不太友好的语法一直饱受诟病,书写一个查询语句可能需要书写一大串的代码,如果能像mybatis--plus一样,支持比较灵活方便的语句生成器那就好了。

于是为elasticsearch而生的ORM框架Easy-Es诞生了,使用及其方便快捷,今天我们就一起来学习easy-es,对比看看原生java-client方便之处在哪儿。

1. Easy-Es简介

Easy-Es是以elasticsearch官方提供的RestHighLevelClient为基础,而开发的一款针对es的ORM框架,类似于es版的mybatis-plus,可以让开发者无需掌握es复杂的DSL语句,只要会mysql语法即可使用es,快速实现es客户端语法

官方文档:www.easy-es.cn/

2. Easy-Es使用

1、引入依赖

xml 复制代码
<!-- 引入easy-es最新版本的依赖-->
        <dependency>
            <groupId>org.dromara.easy-es</groupId>
            <artifactId>easy-es-boot-starter</artifactId>
            <version>2.0.0-beta3</version>
        </dependency>

        <!-- 排除springboot中内置的es依赖,以防和easy-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>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.14.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.14.0</version>
        </dependency>

2、添加配置项,这里只配置了几个基本的配置项,更多配置可参考官网文档:easy-es 配置介绍

yml 复制代码
easy-es: 
  # es地址、账号密码
  address: 192.168.244.11:9200
  username: elastic
  password: elastic

3、在启动类中添加es mapper文件的扫描路径

java 复制代码
@EsMapperScan("com.example.easyesdemo.mapper")

4、创建实体类,通过@IndexName注解申明索引名称及分片数, @IndexField注解申明字段名、数据类型、分词器等,更多介绍参考官方文档:essy-es 注解介绍

java 复制代码
@IndexName(value = "user_easy_es")
@Data
public class UserEasyEs {

    @IndexId(type = IdType.CUSTOMIZE)
    private Long id;

    private String name;

    private Integer age;

    private Integer sex;

    @IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART, searchAnalyzer = Analyzer.IK_SMART)
    private String address;

    @IndexField(fieldType = FieldType.DATE, dateFormat = "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")
    private Date createTime;

    private String createUser;

}

5、创建mapper类,继承BaseEsMapper类,注意这里的mapper一定要创建到第3步中设置的mapper扫描路径下com.example.easyesdemo.mapper

java 复制代码
public interface UserEsMapper extends BaseEsMapper<UserEasyEs> {
}

6、创建controller,书写创建索引、新增、修改、查询的接口

java 复制代码
@RestController
@RequestMapping("es")
@AllArgsConstructor
public class UserEsController {

    private final UserEsMapper userEsMapper;

    /**
     * 创建索引
     * @return
     */
    @GetMapping("create")
    public Boolean createIndex(){
        return userEsMapper.createIndex();
    }

    @GetMapping("save")
    public Integer save(Long id){
        UserEasyEs user = new UserEasyEs();
        user.setId(id);
        user.setName("用户"+id);
        user.setAddress("江苏省无锡市滨湖区");
        user.setAge(30);
        user.setSex(1);
        user.setCreateUser("admin");
        user.setCreateTime(new Date());
        Long count = userEsMapper.selectCount(EsWrappers.lambdaQuery(UserEasyEs.class).eq(UserEasyEs::getId, id));
        if(count > 0){
            return userEsMapper.updateById(user);
        }else{
            return userEsMapper.insert(user);
        }
    }

    @GetMapping("search")
    public List<UserEasyEs> search(String name, String address){
        List<UserEasyEs> userEasyEs = userEsMapper.selectList(
                EsWrappers.lambdaQuery(UserEasyEs.class)
                        .eq(UserEasyEs::getName, name)
                        .match(UserEasyEs::getAddress, address)
                );
        return userEasyEs;
    }

}

7、分别调用几个接口

  • 创建索引 kibana中查询索引,发现创建成功

  • 新增接口 这里新增了4笔 数据新增成功

  • 数据查询

如上便是针对easy-es的简单使用,这里的用法都与mp类似,上手相当简单,不用再写那些复杂的DSL语句了

3. 拓展介绍

  • 条件构造器

上述演示,我们构造查询条件时,使用了EsWrappers来构造条件,用法与mp及其类型,大家根据提示就可以推导出方法如何书写,更详细的使用说明可以查看官方文档:easy-es 条件构造器介绍

  • 索引托管

如果想要自动根据创建的es实体类来创建对应的索引,那么只需要调整索引的托管模式为非手动模式即可,因为这里我不需要自动同步数据,所以选择非平滑模式

yml 复制代码
easy-es:
  global-config:
    process_index_mode: not_smoothly

其中三种模式的区别为: 平滑模式:smoothly,索引的创建、数据更新迁移等都由easy-es自动完成 非平滑模式:not_smoothly,索引自动创建,但不会自动迁移数据 手动模式:manual,全部操作由用户手动完成,默认模式

  • 数据同步

如果数据源是来自mysql, 那么建议使用canal来进行同步,canal的使用可在我主页搜索。 其次还有DataX, Logstash等同步工具,当然你也可以使用easy-es提供的CRUD接口,来手动同步数据

  • 日志打印

通过开启日志,可以在控制台打印执行的DSL语句,更加方便我们在开发阶段进行问题排查

yml 复制代码
logging:
  level:
   tracer: trace # 开启trace级别日志,在开发时可以开启此配置,则控制台可以打印es全部请求信息及DSL语句,为了避免重复,开启此项配置后,可以将EE的print-dsl设置为false.
  • 聚合查询 easy-es实现的聚合查询,只要是针对group by这类聚合,也就是es中的Terms aggregation,以及最大值、最小值、平均值、求和,而对于其他类型的聚合,还在不断更新中,但这里大家也需要了解,es的聚合和mysql的聚合完全是不一样的维度和复杂度,es支持非常多的聚合查询,所以其他类型的实现还需要借助RestHighLevelClient来实现

我们利用easy-es来实现下之前书写的聚合案例

java 复制代码
@RestController
@AllArgsConstructor
@RequestMapping("order")
public class OrderEsController {

    private final OrderTestEsMapper orderEsMapper;

    @GetMapping("search")
    public String search(){
        SearchResponse search = orderEsMapper.search(EsWrappers.lambdaQuery(OrderTest.class).groupBy(OrderTest::getStatus));

        // 包装查询结果
        Aggregations aggregations = search.getAggregations();
        Terms terms = (Terms)aggregations.asList().get(0);
        List<? extends Terms.Bucket> buckets = terms.getBuckets();
        HashMap<String,Long> statusRes = new HashMap<>();
        buckets.forEach(bucket -> {
            statusRes.put(bucket.getKeyAsString(),bucket.getDocCount());
        });
        System.out.println("---聚合结果---");
        System.out.println(statusRes);
        return statusRes.toString();
    }
}

可以看到实际上的查询语句就一行,而其他的都是对返回结果的封装,因为es本身返回的数据是封装到嵌套的对象中的,所以我们需要对其进行包装

对比原始的查询语句,其易用性上的提升还是很明显的

4. 总结

至此对easy-es的介绍就结束了,可以看到如果是针对es实现CRUD上,easy-es表现出非常好的便捷性,而在复杂的聚合查询中,仍然还有进步空间,目前还需要借助RestHighLevelClient,但easy-es的出现,为未来提供更好用的ES ORM框架,提供了希望和方向

文中演示代码见:gitee.com/wuhanxue/wu...

相关推荐
monkey_meng16 分钟前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust
Estar.Lee31 分钟前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
新知图书1 小时前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
盛夏绽放2 小时前
Node.js 和 Socket.IO 实现实时通信
前端·后端·websocket·node.js
Ares-Wang2 小时前
Asp.net Core Hosted Service(托管服务) Timer (定时任务)
后端·asp.net
Rverdoser3 小时前
RabbitMQ的基本概念和入门
开发语言·后端·ruby
Tech Synapse4 小时前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
.生产的驴4 小时前
SpringCloud OpenFeign用户转发在请求头中添加用户信息 微服务内部调用
spring boot·后端·spring·spring cloud·微服务·架构
微信-since811924 小时前
[ruby on rails] 安装docker
后端·docker·ruby on rails
代码吐槽菌6 小时前
基于SSM的毕业论文管理系统【附源码】
java·开发语言·数据库·后端·ssm