springboot整合easy-es实现数据的增删改查

背景

目前公司的一个老项目,查询贼慢,需要想办法提升一下速度,于是就想到了ES,现在尝试一下将ES整合到项目中来提升检索效率。

ES是基于倒排索引实现的,倒排索引中一个表相当于一个索引,表中的每条记录都是一个文档(JSON数据),系统会先对字段数据进行分词,然后给词条建立索引,并映射到文档id。在查询的时候根据输入进行分词,然后根据词条走索引查询文档id,再根据文档id查询文档并放入结果集,最后将结果集返回。

一般来说,ES算是难度较高的一个技术栈,需要中高级才能熟练驾驭,新手入门比较难,因而我选中了对新手更加友好的easy-es,其在ES的基础上做了封装,使得使用起来和MybatisPlus很像,简单上手。

开始使用easy-es之前,建议先看一下避坑指南

Elastic Search下载

ES官网
按照官方推荐下载7.x的ES,我下载了和官方demo一样的7.14.0版本。
在这里插入图片描述
在这里插入图片描述
输入7.14.0搜索该版本并下载
在这里插入图片描述
在这里插入图片描述

下载完成之后解压,并去到bin目录,双击elasticsearch.bat文件启动elasticsearch。

Springboot整合ES

  1. 打开Springboot项目(或创建一个Springboot项目),先全局搜索elastic,看看项目是否已经引入过ES,如果有,需要去掉或者更改版本为7.14.0。印象中不同版本的Springboot默认引入的一定版本的ES。
  2. 在POM文件引入依赖
        <!-- 引入easy-es最新版本的依赖-->
        <dependency>
            <groupId>org.dromara.easy-es</groupId>
            <artifactId>easy-es-boot-starter</artifactId>
            <!--这里Latest Version是指最新版本的依赖,比如2.0.0,可以通过下面的图片获取-->
            <version>2.0.0-beta4</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>

  1. YAML文件增加ES配置(更多配置可以在官网看)
easy-es:
  enable: true #默认为true,若为false则认为不启用本框架
  address: 127.0.0.1:9200 # es的连接地址,必须含端口 若为集群,则可以用逗号隔开 例如:127.0.0.1:9200,127.0.0.2:9200
# username: elastic #若无 则可省略此行配置。因为刚下载的ES默认不用账号密码登录,所以注掉
#  password: WG7WVmuNMtM4GwNYkyWH #若无 则可省略此行配置
  1. 在启动类设置ES的mapper包扫描路径(一般应该设置成带*的通配格式,方便多模块项目的扫描。)同时注意,该mapper的包和mybatisplus的包不能是同一个,不然框架区分不开。
    在这里插入图片描述
@EsMapperScan("org.jeecg.modules.test.esmapper")
@SpringBootApplication
public class JeecgSystemApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(JeecgSystemApplication.class);
    }

    public static void main(String[] args) throws UnknownHostException {
        ConfigurableApplicationContext application = SpringApplication.run(JeecgSystemApplication.class, args);
    }
}
  1. 创建实体类(加上@IndexName注解)
package org.jeecg.modules.message.entity;

import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.IndexName;
import org.dromara.easyes.annotation.rely.Analyzer;
import org.dromara.easyes.annotation.rely.FieldType;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecg.common.system.base.entity.JeecgEntity;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;

import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

@Data
@IndexName
public class SysMessage{
	/** ID */
	@TableId(type = IdType.ASSIGN_ID)
	private java.lang.String id;
	/**推送内容*/
	private java.lang.String esContent;
	/**推送所需参数Json格式*/
	private java.lang.String esParam;
	/**接收人*/
	private java.lang.String esReceiver;
	/**推送失败原因*/
	private java.lang.String esResult;
	/**发送次数*/
	private java.lang.Integer esSendNum;
	/**推送状态 0未推送 1推送成功 2推送失败*/
	private java.lang.String esSendStatus;
	/**推送时间*/
	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
	private java.util.Date esSendTime;
	/**消息标题*/
	private java.lang.String esTitle;
	/**推送方式:1短信 2邮件 3微信*/
	private java.lang.String esType;
	/**备注*/
	private java.lang.String remark;
		/** 创建人 */
	private java.lang.String createBy;
	/** 创建时间 */
	@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	private java.util.Date createTime;
	/** 更新人 */
	private java.lang.String updateBy;
	/** 更新时间 */
	@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	private java.util.Date updateTime;
}

  1. 创建mapper类
package org.jeecg.modules.test.esmapper;


import org.dromara.easyes.core.core.BaseEsMapper;
import org.jeecg.modules.message.entity.SysMessage;
public interface DocumentMapper extends BaseEsMapper<SysMessage> {

}
  1. 编写测试类
	@Resource
	private DocumentMapper documentMapper;

	@GetMapping("/createIndex")
	@ApiOperation("创建索引")
	public Object createIndex(String a){
		Boolean index = documentMapper.createIndex();
		System.out.println(index);
		return index;
	}

	@GetMapping("/createDoc")
	@ApiOperation("创建文档")
	public Object createDoc(String a,String b){
		SysMessage sysMessage=new SysMessage();
		sysMessage.setEsContent(a);
		sysMessage.setEsTitle(b);
		sysMessage.setEsReceiver("系统管理员");
		sysMessage.setEsSendNum(10);
		Integer insert = documentMapper.insert(sysMessage);
		return insert;
	}
	@GetMapping("/updateDoc")
	@ApiOperation("updateDoc")
	public Object updateDoc(String a){
		LambdaEsUpdateWrapper<SysMessage> wrapper=new LambdaEsUpdateWrapper<>();
		wrapper.eq(SysMessage::getEsContent,a)
				.set(SysMessage::getEsContent,"更改后的标题");
		Integer update = documentMapper.update(null, wrapper);
		return update;
	}
	@GetMapping("/getDoc")
	@ApiOperation("查询文档")
	public Object getDoc(String a){
		List<SysMessage> list = EsWrappers.lambdaChainQuery(documentMapper).like(SysMessage::getEsContent, a).list();
		return list;
	}
  1. 浏览器安装一个ES可视化插件。我安装的是es-client
    在这里插入图片描述
    添加连接
    在这里插入图片描述
    在这里插入图片描述
    选中创建的连接,目前还没有索引。
    在这里插入图片描述
  2. 测试
    启动Springboot项目,调用createIndex接口,创建索引 。然后回到浏览器插件,点击刷新,可以看到创建了一个索引。
    在这里插入图片描述
    调用createDoc接口,创建一个文档记录
    在这里插入图片描述
    点击左侧的数据展示选项,右上角选中创建的索引,点击刷新,可以看到多了一条记录。
    在这里插入图片描述
    调用getDoc接口,查询记录,成功查出。
    在这里插入图片描述
    更新的语法和MybatisPlus的wrapper差不多。先用查询条件eq,in等去筛选要更新的记录,然后用set去设置新的值,然后调用update方法即可。(如下,通过“测试内容”找到记录,并将其的标题改成新的内容)
    在这里插入图片描述
    在浏览器刷新,可以看到数据更新了。
    在这里插入图片描述

删除的语法比更新还简单,也是创建一个esupdatewrapper,用eq、in等筛选,然后调用delete方法就可以了,就不演示了。

总结

Springboot整合ES最大可能遇到的问题就是ES版本的问题,也就是依赖冲突。如果依赖冲突,在项目启动的时候会有一个ERROR日志提醒,看到了就想办法去掉原来带着的ES依赖或者更改依赖版本为7.14.0

关于ES的数据更新,就要去了解ES同步数据库相关的知识了。

想要了解easy-es的更多特性,建议去看easy-es的官网文档

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里提供一个基于SpringBoot整合Easy-Elasticsearch、Canal、Kafka实现MySQL数据同步的代码示例。 1. 添加依赖 ```xml <!-- easy-elastic --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easy-elastic</artifactId> <version>1.2.5</version> </dependency> <!-- canal --> <dependency> <groupId>com.alibaba</groupId> <artifactId>canal.client</artifactId> <version>1.1.4</version> </dependency> <!-- kafka --> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>2.5.4.RELEASE</version> </dependency> ``` 2. 配置文件 ```yaml # Easy-Elasticsearch easy.elasticsearch: enable: true urls: http://localhost:9200 scan.package: com.example.elasticsearchdemo.entity # Canal canal: host: 127.0.0.1 port: 11111 username: canal password: canal destination: example filter: - .* mq: topic: example partition: 0 groupId: example # Kafka spring.kafka.bootstrap-servers: localhost:9092 spring.kafka.consumer.group-id: example ``` 3. 实现 Canal 客户端 ```java @Component public class CanalClient { @Autowired private CanalConfig canalConfig; @Autowired private KafkaTemplate<String, String> kafkaTemplate; /** * 启动 Canal 客户端 */ @PostConstruct public void start() { CanalConnector connector = CanalConnectors.newSingleConnector( new InetSocketAddress(canalConfig.getHost(), canalConfig.getPort()), canalConfig.getDestination(), canalConfig.getUsername(), canalConfig.getPassword()); int batchSize = 1000; try { connector.connect(); connector.subscribe(canalConfig.getFilter()); connector.rollback(); while (true) { Message message = connector.getWithoutAck(batchSize); long batchId = message.getId(); int size = message.getEntries().size(); if (batchId == -1 || size == 0) { Thread.sleep(1000); } else { List<CanalEntry.Entry> entries = message.getEntries(); for (CanalEntry.Entry entry : entries) { if (entry.getEntryType() == CanalEntry.EntryType.ROWDATA) { String tableName = entry.getHeader().getTableName(); CanalEntry.RowChange rowChange = CanalEntry.RowChange.parseFrom(entry.getStoreValue()); CanalEntry.EventType eventType = rowChange.getEventType(); for (CanalEntry.RowData rowData : rowChange.getRowDatasList()) { JSONObject data = new JSONObject(); data.put("tableName", tableName); data.put("eventType", eventType); data.put("before", getColumns(rowData.getBeforeColumnsList())); data.put("after", getColumns(rowData.getAfterColumnsList())); kafkaTemplate.send(canalConfig.getMq().getTopic(), data.toJSONString()); } } } connector.ack(batchId); } } } catch (Exception e) { e.printStackTrace(); } finally { connector.disconnect(); } } /** * 获取列数据 */ private JSONObject getColumns(List<CanalEntry.Column> columns) { JSONObject data = new JSONObject(); for (CanalEntry.Column column : columns) { data.put(column.getName(), column.getValue()); } return data; } } ``` 4. 实现 Kafka 消费者 ```java @Component public class KafkaConsumer { @KafkaListener(topics = "${spring.kafka.consumer.topic}") public void receive(String message) { JSONObject data = JSONObject.parseObject(message); String tableName = data.getString("tableName"); CanalEntry.EventType eventType = CanalEntry.EventType.valueOf(data.getString("eventType")); JSONObject before = data.getJSONObject("before"); JSONObject after = data.getJSONObject("after"); switch (eventType) { case INSERT: // TODO: 处理插入操作 break; case UPDATE: // TODO: 处理更新操作 break; case DELETE: // TODO: 处理删除操作 break; default: break; } } } ``` 5. 实现数据同步逻辑 此处省略,具体实现根据业务需求而定。 以上就是一个基于SpringBoot整合Easy-Elasticsearch、Canal、Kafka实现MySQL数据同步的代码示例。需要注意的是,本示例只提供了基本思路和代码框架,需要根据实际业务场景进行完善和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值