Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >优雅而强大:用easy-es简化ElasticSearch操作

优雅而强大:用easy-es简化ElasticSearch操作

作者头像
架构狂人
发布于 2023-09-21 12:35:36
发布于 2023-09-21 12:35:36
3K00
代码可运行
举报
文章被收录于专栏:架构狂人架构狂人
运行总次数:0
代码可运行

使用过Spring Data操作ES的小伙伴应该有所了解,它只能实现一些非常基本的数据管理工作,一旦遇到稍微复杂点的查询,基本都要依赖ES官方提供的RestHighLevelClient,Spring Data只是在其基础上进行了简单的封装。最近发现一款更优雅的ES ORM框架Easy-Es,使用它能像MyBatis-Plus一样操作ES,今天就以一个实际的mall商城项目中的商品搜索功能为例,来聊聊它的使用!

Easy-Es简介

Easy-Es(简称EE)是基于Elasticsearch(简称ES)官方提供的RestHighLevelClient开发的ORM框架,旨在简化开发流程并提高效率。EE在保持RestHighLevelClient原有功能的基础上进行增强,而不做任何改变。与Mybatis-Plus(简称MP)相比,EE的用法非常相似,如果您之前使用过MP,应该能够很快上手EE。EE的设计理念是:将简单、易用和方便留给用户,而将复杂的任务交由框架来处理。

EE的主要特性如下:

  • 全自动索引管理:开发者无需繁琐地处理索引的创建、更新和数据迁移等步骤,框架会自动完成这些任务。
  • 屏蔽语言差异:开发者只需要熟悉MySQL语法,就能够轻松地使用ES进行开发。
  • 更少的代码量:相比直接使用官方提供的RestHighLevelClient,使用EE平均可以节省3-5倍的代码量来进行相同的查询操作。
  • 零魔法值:字段名称会直接从实体中获取,无需手动编写。
  • 无额外学习成本:如果开发者已经熟悉国内最受欢迎的Mybatis-Plus的用法,那么可以无缝迁移至EE,无需额外学习成本。

MySQL与Easy-Es语法对比

集成及配置

  • 首先需要在pom.xml中添加Easy-Es的相关依赖;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependencyManagement>
    <dependencies>
        <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>
    </dependencies>
</dependencyManagement>
  • 再修改配置文件application.yml对Easy-Es进行配置。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
easy-es:
  # 是否开启EE自动配置
  enable: true
  # ES连接地址+端口
  address: localhost:9200
  # 关闭自带banner
  banner: false
  • 添加Easy-Es的Java配置,使用@EsMapperScan配置好Easy-Es的Mapper接口和文档对象路径,如果你使用了MyBatis-Plus的话,需要和它的扫描路径区分开来。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * EasyEs配置类
 * Created by macro on 2022/9/16.
 */
@Configuration
@EsMapperScan("com.macro.mall.tiny.easyes")
public class EasyEsConfig {
}

使用

注解的使用

  • 首先我们需要创建文档对象EsProduct,然后给类和字段添加上Easy-Es的注解;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 搜索商品的信息
 * Created by macro on 2018/6/19.
 */
@Data
@EqualsAndHashCode
@IndexName(value = "pms", shardsNum = 1, replicasNum = 0)
public class EsProduct implements Serializable {
    private static final long serialVersionUID = -1L;
    @IndexId(type = IdType.CUSTOMIZE)
    private Long id;
    @IndexField(fieldType = FieldType.KEYWORD)
    private String productSn;
    private Long brandId;
    @IndexField(fieldType = FieldType.KEYWORD)
    private String brandName;
    private Long productCategoryId;
    @IndexField(fieldType = FieldType.KEYWORD)
    private String productCategoryName;
    private String pic;
    @IndexField(fieldType = FieldType.TEXT, analyzer = "ik_max_word")
    private String name;
    @IndexField(fieldType = FieldType.TEXT, analyzer = "ik_max_word")
    private String subTitle;
    @IndexField(fieldType = FieldType.TEXT, analyzer = "ik_max_word")
    private String keywords;
    private BigDecimal price;
    private Integer sale;
    private Integer newStatus;
    private Integer recommandStatus;
    private Integer stock;
    private Integer promotionType;
    private Integer sort;
    @IndexField(fieldType = FieldType.NESTED, nestedClass = EsProductAttributeValue.class)
    private List<EsProductAttributeValue> attrValueList;
    @Score
    private Float score;
}
  • EsProduct中的注解具体说明如下:
  • EsProduct中嵌套类型EsProductAttributeValue的代码如下。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 搜索商品的属性信息
 * Created by macro on 2018/6/27.
 */
@Data
@EqualsAndHashCode
public class EsProductAttributeValue implements Serializable {
    private static final long serialVersionUID = 1L;
    @IndexField(fieldType = FieldType.LONG)
    private Long id;
    @IndexField(fieldType = FieldType.KEYWORD)
    private Long productAttributeId;
    //属性值
    @IndexField(fieldType = FieldType.KEYWORD)
    private String value;
    //属性参数:0->规格;1->参数
    @IndexField(fieldType = FieldType.INTEGER)
    private Integer type;
    //属性名称
    @IndexField(fieldType=FieldType.KEYWORD)
    private String name;
}

商品信息维护

下面我们来实现几个简单的商品信息维护接口,包括商品信息的导入、创建和删除。

  • 首先我们需要定义一个Mapper,继承BaseEsMapper;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 商品ES操作类
 * Created by macro on 2018/6/19.
 */
public interface EsProductMapper extends BaseEsMapper<EsProduct> {

}

  • 然后在Service实现类中直接使用EsProductMapper内置方法实现即可,是不是和MyBatis-Plus的用法一致?
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 搜索商品管理Service实现类
 * Created by macro on 2018/6/19.
 */
@Service
public class EsProductServiceImpl implements EsProductService {
    @Autowired
    private EsProductDao productDao;
    @Autowired
    private EsProductMapper esProductMapper;
    @Override
    public int importAll() {
        List<EsProduct> esProductList = productDao.getAllEsProductList(null);
        return esProductMapper.insertBatch(esProductList);
    }

    @Override
    public void delete(Long id) {
        esProductMapper.deleteById(id);
    }

    @Override
    public EsProduct create(Long id) {
        EsProduct result = null;
        List<EsProduct> esProductList = productDao.getAllEsProductList(id);
        if (esProductList.size() > 0) {
            result = esProductList.get(0);
            esProductMapper.insert(result);
        }
        return result;
    }

    @Override
    public void delete(List<Long> ids) {
        if (!CollectionUtils.isEmpty(ids)) {
            esProductMapper.deleteBatchIds(ids);
        }
    }
}

简单商品搜索

下面我们来实现一个最简单的商品搜索,分页搜索商品名称、副标题、关键词中包含指定关键字的商品。

  • 通过QueryWrapper来构造查询条件,然后使用Mapper中的方法来进行查询,使用过MyBatis-Plus的小伙伴应该很熟悉了;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 搜索商品管理Service实现类
 * Created by macro on 2018/6/19.
 */
@Service
public class EsProductServiceImpl implements EsProductService {
    @Autowired
    private EsProductMapper esProductMapper;
    @Override
    public PageInfo<EsProduct> search(String keyword, Integer pageNum, Integer pageSize) {
        LambdaEsQueryWrapper<EsProduct> wrapper = new LambdaEsQueryWrapper<>();
        if(StrUtil.isEmpty(keyword)){
            wrapper.matchAllQuery();
        }else{
            wrapper.multiMatchQuery(keyword,EsProduct::getName,EsProduct::getSubTitle,EsProduct::getKeywords);
        }
        return esProductMapper.pageQuery(wrapper, pageNum, pageSize);
    }
}

  • 使用Swagger访问接口后,可以在控制台输出查看生成的DSL语句,访问地址:http://localhost:8080/swagger-ui/
  • 把DSL语句直接复制Kibana中即可执行查看结果了,这和我们手写DSL语句没什么两样的。

综合商品搜索

下面我们来实现一个复杂的商品搜索,涉及到过滤、不同字段匹配权重不同以及可以进行排序。

  • 首先来说需求,按输入的关键字搜索商品名称(权重10)、副标题(权重5)和关键词(权重2),可以按品牌和分类进行筛选,可以有5种排序方式,默认按相关度进行排序,看下接口文档有助于理解;
  • 这个功能之前使用Spring Data来实现非常复杂,使用Easy-Es来实现确实简洁不少,下面是使用Easy-Es的实现方式;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 搜索商品管理Service实现类
 * Created by macro on 2018/6/19.
 */
@Service
public class EsProductServiceImpl implements EsProductService {
    @Autowired
    private EsProductMapper esProductMapper;
    @Override
    public PageInfo<EsProduct> search(String keyword, Long brandId, Long productCategoryId, Integer pageNum, Integer pageSize,Integer sort) {
        LambdaEsQueryWrapper<EsProduct> wrapper = new LambdaEsQueryWrapper<>();
        //过滤
        if (brandId != null || productCategoryId != null) {
            if (brandId != null) {
                wrapper.eq(EsProduct::getBrandId,brandId);
            }
            if (productCategoryId != null) {
                wrapper.eq(EsProduct::getProductCategoryId,productCategoryId).enableMust2Filter(true);
            }
        }
        //搜索
        if (StrUtil.isEmpty(keyword)) {
            wrapper.matchAllQuery();
        } else {
            wrapper.and(i -> i.match(EsProduct::getName, keyword, 10f)
                    .or().match(EsProduct::getSubTitle, keyword, 5f)
                    .or().match(EsProduct::getKeywords, keyword, 2f));
        }
        //排序
        if(sort==1){
            //按新品从新到旧
            wrapper.orderByDesc(EsProduct::getId);
        }else if(sort==2){
            //按销量从高到低
            wrapper.orderByDesc(EsProduct::getSale);
        }else if(sort==3){
            //按价格从低到高
            wrapper.orderByAsc(EsProduct::getPrice);
        }else if(sort==4){
            //按价格从高到低
            wrapper.orderByDesc(EsProduct::getPrice);
        }else{
            //按相关度
            wrapper.sortByScore(SortOrder.DESC);
        }
        return esProductMapper.pageQuery(wrapper, pageNum, pageSize);
    }
}

  • 再对比下之前使用Spring Data的实现方式,没有QueryWrapper来构造条件,还要硬编码字段名称,确实优雅了不少!

相关商品推荐

当我们查看相关商品的时候,一般底部会有一些商品推荐,这里简单来实现下。

  • 首先来说下需求,可以根据指定商品的ID来查找相关商品,看下接口文档有助于理解;
  • 这里我们的实现原理是这样的:首先根据ID获取指定商品信息,然后以指定商品的名称、品牌和分类来搜索商品,并且要过滤掉当前商品,调整搜索条件中的权重以获取最好的匹配度;
  • 使用Easy-Es来实现依旧是那么简洁!
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 搜索商品管理Service实现类
 * Created by macro on 2018/6/19.
 */
@Service
public class EsProductServiceImpl implements EsProductService {
    @Autowired
    private EsProductMapper esProductMapper;
    @Override
    public PageInfo<EsProduct> recommend(Long id, Integer pageNum, Integer pageSize) {
        LambdaEsQueryWrapper<EsProduct> wrapper = new LambdaEsQueryWrapper<>();
        List<EsProduct> esProductList = productDao.getAllEsProductList(id);
        if (esProductList.size() > 0) {
            EsProduct esProduct = esProductList.get(0);
            String keyword = esProduct.getName();
            Long brandId = esProduct.getBrandId();
            Long productCategoryId = esProduct.getProductCategoryId();
            //用于过滤掉相同的商品
            wrapper.ne(EsProduct::getId,id);
            //根据商品标题、品牌、分类进行搜索
            wrapper.and(i -> i.match(EsProduct::getName, keyword, 8f)
                    .or().match(EsProduct::getSubTitle, keyword, 2f)
                    .or().match(EsProduct::getKeywords, keyword, 2f)
                    .or().match(EsProduct::getBrandId, brandId, 5f)
                    .or().match(EsProduct::getProductCategoryId, productCategoryId, 3f));
            return esProductMapper.pageQuery(wrapper, pageNum, pageSize);
        }
        return esProductMapper.pageQuery(wrapper, pageNum, pageSize);
    }
}

总结

今天主要介绍了Easy-Es的一些常见的用法,确实使用Easy-Es更简单,但是对于复杂的聚合搜索功能,还是需要使用原生的RestHighLevelClient用法来实现。使用Easy-Es来操作ES确实足够优雅,它类似MyBatis-Plus的用法能大大降低我们的学习成本,快速完成开发工作!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-09-17 08:00,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 顶尖架构师栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
横空出世!MyBatis-Plus同款ES ORM框架,用起来够优雅!
Easy-Es(简称EE)是一款基于Elasticsearch(简称ES)官方提供的RestHighLevelClient打造的ORM开发框架,在RestHighLevelClient的基础上,只做增强不做改变,为简化开发、提高效率而生。EE和Mybatis-Plus(简称MP)的用法非常相似,如果你之前使用过MP的话,应该能很快上手EE。EE的理念是:把简单、易用、方便留给用户,把复杂留给框架。
macrozheng
2022/12/14
1.3K0
横空出世!MyBatis-Plus同款ES ORM框架,用起来够优雅!
Elasticsearch项目实战,商品搜索功能设计与实现!
在SpringBoot中使用Elasticsearch本文不再赘述,直接参考《mall整合Elasticsearch实现商品搜索》即可。这里需要提一下,对于需要进行中文分词的字段,我们直接使用@Field注解将analyzer属性设置为ik_max_word即可。
macrozheng
2020/04/24
3.9K0
mall整合Elasticsearch实现商品搜索
1.下载Elasticsearch6.2.2的zip包,并解压到指定目录,下载地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-2-2
macrozheng
2019/07/22
7010
mall整合Elasticsearch实现商品搜索
全文检索工具:第一章:Spring-data-elasticSearch搜索
@Document(indexName = "search11", type = "article",shards = 1,replicas = 0)
Java廖志伟
2022/09/28
4430
全文检索工具:第一章:Spring-data-elasticSearch搜索
SpringData集成Elasticsearch
Spring Data 是一个用于简化数据库、非关系型数据库、索引库访问,并支持云服务的 开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持 map-reduce 框架和云计 算数据服务。 Spring Data 可以极大的简化 JPA(Elasticsearch„)的写法,可以在几乎不用 写实现的情况下,实现对数据的访问和操作。除了 CRUD 外,还包括如分页、排序等一些 常用的功能。
鱼找水需要时间
2023/02/16
6510
SpringData集成Elasticsearch
springboot集成elasticsearch7实现全文检索及分页
elasticsearch系列文章前面已经更新过三篇(https://blog.csdn.net/lsqingfeng/category_10219329.html)(建议先看下这三篇文章),分别讲解了elasticsearch7.2的安装,和springboot的集成以及简单的使用。前面都是通过demo的方式,主要讲解了他的一下简单使用,最近已经将es成功应用到了项目当中,本篇文章主要系统的介绍一下到底在项目中该如何使用es.
一缕82年的清风
2021/12/06
2.5K0
springboot集成elasticsearch7实现全文检索及分页
【ES三周年】吊打Elasticsearch 和Java API(进阶保姆级教程-3)
上一篇我们通过kibana的可视化界面,对es的索引以及文档的常用操作做了毕竟详细的总结,本篇将介绍如何使用java完成对es的操作,这也是实际开发中将要涉及到的。
北京-宏哥
2023/04/12
21K1
【ES三周年】吊打Elasticsearch 和Java API(进阶保姆级教程-3)
ElasticSearch全文搜索引擎 -Spring Boot操作ES(SpringData概述、Spring Data Elasticsearch、基本操作、ElasticSearch操作文档)
Spring Data是spring提供的一套连接各种第三方数据源的框架集,它支持连接很多第三方数据源,例如:
鱼找水需要时间
2023/02/16
2.6K0
ElasticSearch全文搜索引擎 -Spring Boot操作ES(SpringData概述、Spring Data Elasticsearch、基本操作、ElasticSearch操作文档)
ElasticSearch 多框架集成
Spring Data 是一个用于简化数据库、非关系型数据库、索引库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持 map-reduce 框架和云计 算数据服务。Spring Data 可以极大的简化 JPA(Elasticsearch ......)的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了 CRUD 外,还包括如分页、排序等一些常用的功能。
用户9615083
2022/12/25
8240
ElasticSearch 多框架集成
全文检索工具:第一章:Spring-data-elasticSearch搜索
更多内容请见原文,原文转载自:https://blog.csdn.net/weixin_44519496/article/details/120482353
马克社区
2022/12/30
2280
全面升级!一套基于Spring Boot 3+JDK17的实战项目!
这里还是先简单介绍下mall项目吧,mall项目是一套基于 SpringBoot + Vue + uni-app 实现的电商系统(Github标星60K),采用Docker容器化部署。包括前台商城项目和后台管理系统,能支持完整的订单流程!涵盖商品、订单、购物车、权限、优惠券、会员、支付等功能!
macrozheng
2024/04/25
1.3K0
全面升级!一套基于Spring Boot 3+JDK17的实战项目!
还在用HttpUtil?SpringBoot 3全新HTTP客户端工具来了,用起来够优雅!
Http Interface让你可以像定义Java接口那样定义HTTP服务,而且用法和你平时写Controller中方法完全一致。它会为这些HTTP服务接口自动生成代理实现类,底层是基于Webflux的WebClient实现的。
macrozheng
2024/01/23
2.7K0
还在用HttpUtil?SpringBoot 3全新HTTP客户端工具来了,用起来够优雅!
SpringBoot3集成ElasticSearch
Elasticsearch是一个分布式、RESTful风格的搜索和数据分析引擎,适用于各种数据类型,数字、文本、地理位置、结构化数据、非结构化数据;
知了一笑
2023/09/01
1.4K0
SpringBoot3集成ElasticSearch
谷粒商城-高级篇(检索服务)
将资料中的前端页面放到 search 服务模块下的 resource/templates 下;
OY
2022/03/20
1.3K0
谷粒商城-高级篇(检索服务)
【Elasticsearch】整合Spring Data Elasticsearch
官方文档:Java High Level REST Client | Java REST Client [6.8] | Elastic
陶然同学
2023/02/24
1.4K0
【Elasticsearch】整合Spring Data Elasticsearch
ES实战系列01:基于SpringBoot和RestHighLevelClient 快速搭建博客搜索系统
通过4个博客检索场景,巩固之前所学的全文搜索 Full Text Queries 和 基于词项的 Term lever Queries,同时通过组合查询的Bool query 完成复杂检索,并应用相关度知识对相关性评分进行控制。
方才编程_公众号同名
2020/11/13
1.6K0
ES实战系列01:基于SpringBoot和RestHighLevelClient 快速搭建博客搜索系统
还在用HttpUtil?SpringBoot 3.0全新HTTP客户端工具来了,用起来够优雅!
Http Interface让你可以像定义Java接口那样定义HTTP服务,而且用法和你平时写Controller中方法完全一致。它会为这些HTTP服务接口自动生成代理实现类,底层是基于Webflux的WebClient实现的。
macrozheng
2022/12/14
3.6K0
还在用HttpUtil?SpringBoot 3.0全新HTTP客户端工具来了,用起来够优雅!
【全文检索_08】Spring Data Elasticsearch
  Spring Data Elasticsearch 是 Spring Data 项目的一部分,该项目旨在为新数据存储提供熟悉且一致的基于 Spring 的编程模型,同时保留特定于存储的功能。Spring Data Elasticsearch 项目提供了与 Elasticsearch 搜索引擎的集成。 Spring Data Elasticsearch 的关键功能区域是一个以 POJO 为中心的模型,该模型用于与 Elastichsearch 文档进行交互并轻松编写存储库样式的数据访问层。   从 Elasticsearch 7 开始不推荐使用 TransportClient,并将在 Elasticsearch 8 中将其删除。Spring Data Elasticsearch 也支持 TransportClient,前提是使用的 Elasticsearch 中可用,Spring Data Elasticsearch 从 4.0 版本开始已弃用使用 TransportClient 的类。现在 High Level REST Client 是 Elasticsearch 的默认客户端,它在接受并返回完全相同的请求/响应对象时直接替代 TransportClient。
Demo_Null
2021/03/02
2.4K0
【全文检索_08】Spring Data Elasticsearch
springboot集成es7.2自定义注解创建索引
各位好,我们把之前的坑填一下,我在上上篇文章中写了springboot集成es7 的方法,并且集成了es原生客户端 High Level Rest Client, 也说明了原因, 我用的版本较高, spring-data封装的es版本较低,所以使用了原生的。
一缕82年的清风
2021/12/06
1.5K0
springboot集成es7.2自定义注解创建索引
8_搭建商城搜索微服务[通俗易懂]
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/152834.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/12
6960
8_搭建商城搜索微服务[通俗易懂]
推荐阅读
相关推荐
横空出世!MyBatis-Plus同款ES ORM框架,用起来够优雅!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验