# elasticsearch-demo **Repository Path**: learning_demo/elasticsearch-demo ## Basic Information - **Project Name**: elasticsearch-demo - **Description**: anquing-demo-elasticsearch - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-04-20 - **Last Updated**: 2022-06-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ##### 文件项目整合SpringBoot2.4.5 + elasticsearch7.9.3 + jpa + mysql,内含mysql及es实现的简单的全文检索例子, #### 1.elasticsearch版本的选取 每个SpringBoot版本都会有一个兼容性最好的elasticsearch版本,那么怎么确定到底是哪个版本呢? 在引入elasticsearch依赖包后,查看到的elasticsearch版本号则为最合适版本。 ~~~~ org.springframework.boot spring-boot-starter-data-elasticsearch ~~~~ #### 2.elasticsearch7.9.3下载安装,后面的IK Analysis、Kibana、Logstash的版本号也是与elasticsearch保持一致 下载:elasticsearch下载页面网址:https://www.elastic.co/cn/downloads/elasticsearch 查看 past releases ,选择7.9.3版本下载解压; 配置:elasticsearch.yml ~~~~ cluster.name: Elasticsearch #Elasticsearch 名称 node.name: node-1 #节点名称 network.host: 0.0.0.0 #0.0.0.0对外开放,如对特定ip开放则改为指定ip http.port: 9200 #端口默认为9200 可以更改 cluster.initial_master_nodes: ["node-1"] #集群节点 ~~~~ 启动:进入\elasticsearch-7.9.3\bin,双击elasticsearch.bat 或者 在cmd窗口进入bin目录后执行elasticsearch 问题:如在安装中遇到jdk相关问题,可以参与该文章:https://blog.csdn.net/luckyming_520/article/details/105226432 问题1: ~~~~ Warning: with JDK 8 on Windows, Elasticsearch may be unable to derive correct ergonomic settings due to a JDK issue (JDK-8074459). Please use a newer version of Java. ~~~~ 使用es自带jdk: 在Elasticsearch安装目录下的bin目录下,找到elasticsearch-env.bat,使用记事本打开,在 `if "%JAVA_HOME%" == ""` 将条件判断去掉,结果如下: ~~~~ rem if "%JAVA_HOME%" == "" ( set JAVA="%ES_HOME%\jdk\bin\java.exe" set JAVA_HOME="%ES_HOME%\jdk" set JAVA_TYPE=bundled jdk rem ) else ( rem set JAVA="%JAVA_HOME%\bin\java.exe" rem set JAVA_TYPE=JAVA_HOME rem ) ~~~~ 验证:浏览器访问:localhost:9200,(HTTP协议默认端口为9200,TCP协议默认端口为9300(SpringBoot使用TCP)) 集群模式(未验证): 启动命令:elasticsearch -Ecluster.name=集群名称 -Enode.name=节点名称 默认情况,一台主机下只能启动一个ES,可通过修elasticsearch.yml中node.max_local_storage_nodes: 10,表示同一台机器上最多可以运行10个节点 #### 3.kibana7.9.3下载安装 下载:kibana下载页面网址:https://www.elastic.co/cn/downloads/kibana 查看 past releases ,选择7.9.3版本下载解压; 配置:kibana.yml ~~~~ server.port: 5601 #端口 server.host: "0.0.0.0" elasticsearch.hosts: ["http://localhost:9200"] #elasticsearch地址 i18n.locale: "zh-CN" #可视化页面中文 ~~~~ 启动:进入\kibana-7.9.3-windows-x86_64\bin,双击kibana.bat(要在es之后启动) 验证:浏览器访问:http://localhost:5601 在左菜单栏点击开发工具进行对es进行操作 ~~~~ 1.添加 put test/_doc/1 {"body":"here"} 2.查询 get test/_doc/1 ~~~~ #### 4.IK Analysis下载安装 ES分词器有standard(默认)、simple、whitespace、language,但对中文不怎么适用,故使用IK Analysis分词器 IK Analysis下载页面网址:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.9.3 选择elasticsearch-analysis-ik-7.9.3.zip下载解压; 解压后的文件夹改名为ik,并复制到Elasticsearch的plugins目录下; 重启es即可; 验证(ik 词器有两种模式:ik_max_word 和 ik_smart 模式): 在kibana 控制台中测试(_analyze): ~~~~ post _analyze {"text":"中华人民共和国人民大会堂","analyzer":"standard" } post localhost:9200/_analyze {"text":"中华人民共和国人民大会堂","analyzer":"ik_smart" } post localhost:9200/_analyze {"text":"中华人民共和国人民大会堂","analyzer":"ik_max_word" } ~~~~ 如果要添加自定义词语,可以在ik插件config目录下的dic文件中添加 #### 5.Logstash下载安装及配置 Logstash 下载页面网址:https://www.elastic.co/cn/downloads/logstash 查看 past releases ,选择7.9.3版本下载解压; 配置: - 复制mysql驱动到\logstash-7.9.3目录(根据mysql版本选择,这个例子使用mysql-connector-java-8.0.23.jar) - 在\logstash-7.9.3\config目录下创建mysql.conf,内容为: ~~~~ # mysql -> Logstash -> Elasticsearch pipeline. input { jdbc { #jdbc 驱动 jdbc_driver_library => "D:\\app\\es\\logstash-7.9.3\\mysql-connector-java-8.0.23.jar" #要使用的驱动包类 jdbc_driver_class => "com.mysql.cj.jdbc.Driver" # mysql数据库的连接 jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/elasticsearch" #mysql 用户 jdbc_user => "root" #mysql 密码 jdbc_password => "root" # 定时器 schedule => "* * * * *" # 启动时清空上次的sql_last_value记录,测试中设置为true,方便测试 clean_run => true # 你要执行的语句 statement => "SELECT * FROM blog where update_time > :sql_last_value and update_time < now() order by update_time desc" } } filter { # delete_flag =1为删除或者禁用的数据,这里判断然后给加上delete_flag标识 # 我理解的action相当于 @metadata对象的一个属性,应该还可以加其他的,比如[@metadata][test] if [delete_flag] == 1 { mutate{ add_field => { "[@metadata][action]" => "delete"}} } else { mutate{ add_field => { "[@metadata][action]" => "index"}} } } output { elasticsearch { # 主要实现想法,就来源于这里action可以指定,那么我前面给数据打上标识,就可以实现删除了 action => "%{[@metadata][action]}" hosts => ["http://localhost:9200"] index => "blog" document_id => "%{id}" #user => "elastic" #password => "changeme" } } ~~~~ ~~~~ #多表配置,未验证 input { stdin {} jdbc { # mysql 数据库链接,shop为数据库名 jdbc_connection_string => "jdbc:mysql://114.67.169.20:3306/myblog" # 用户名和密码 jdbc_user => "root" jdbc_password => "Wylc!@#$5" # 驱动 jdbc_driver_library => "C:/softs/elk/logstash-7.2.0/mysqletc/mysql-connector-java-8.0.13.jar" # 驱动类名 jdbc_driver_class => "com.mysql.cj.jdbc.Driver" jdbc_paging_enabled => "true" jdbc_page_size => "50000" # 执行的sql 文件路径+名称 statement_filepath => "C:/softs/elk/logstash-7.2.0/mysqletc/soul.sql" # 设置监听间隔 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新 schedule => "* * * * *" # 索引类型 type => "soul" } jdbc { # mysql 数据库链接,shop为数据库名 jdbc_connection_string => "jdbc:mysql://114.67.169.20:3306/myblog" # 用户名和密码 jdbc_user => "root" jdbc_password => "Wylc!@#$5" # 驱动 jdbc_driver_library => "C:/softs/elk/logstash-7.2.0/mysqletc/mysql-connector-java-8.0.13.jar" # 驱动类名 jdbc_driver_class => "com.mysql.cj.jdbc.Driver" jdbc_paging_enabled => "true" jdbc_page_size => "50000" # 执行的sql 文件路径+名称 statement_filepath => "C:/softs/elk/logstash-7.2.0/mysqletc/mto_user.sql" # 设置监听间隔 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新 schedule => "* * * * *" # 索引类型 type => "mto_user" } } filter { json { source => "message" remove_field => ["message"] } } output { if [type]=="soul"{ elasticsearch { hosts => ["localhost:9200"] index => "soul" document_id => "%{id}" } } if [type]=="mto_user"{ elasticsearch { hosts => ["localhost:9200"] index => "mto_user" document_id => "%{id}" } } stdout { codec => json_lines } } ~~~~ 启动: ~~~~ cd /d D:\app\es\logstash-7.9.3\bin logstash -f ../config/mysql.conf ~~~~ 验证: 到kibana开发工具查询相索引,看内容是否发生变更 `get /blog/_doc/1` #### 5.ES与MySQL同步数据 同步通常分为全量同步与增量同步(binlog) 利用binlog进行增量同步的有: - alibaba/**canal** - siddontang/**go-mysql-elsticsearch**(开发中) 本文推荐的工具是**logstash**(通过update时间节点查询推送,es根据id进行更新(删除后再插入)) ,配置简单,零代码入侵 #### 6.编码 配置文件:application.yml ~~~~ server: port: 8083 spring: mvc: static-path-pattern: /** jackson: date-format: yyyy-MM-dd HH:mm:ss data: #数据源 datasource: url: jdbc:mysql://127.0.0.1:3306/elasticsearch?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&allowMultiQueries=true&tinyInt1isBit=false username: root password: root # 5.8以前需要使用 com.mysql.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver # Hikari SpringBoot默认连接池 hikari: maximum-pool-size: 20 minimum-idle: 5 #jpa相关 jpa: hibernate: ddl-auto: update show-sql: true database-platform: org.hibernate.dialect.MySQLDialect #elasticsearch elasticsearch: rest: uris: localhost:9200 logging: level: root: INFO org.springframework.data.convert.CustomConversions: ERROR ~~~~ dao层使用JpaRepository、ElasticsearchRepository 测试接口: ~~~~ /** * @author wangqq65 * @since 2021/4/20 13:52 */ @RestController @RequestMapping("/demo") public class DemoController { @Resource private BlogService blogService; @Resource private EsBlogService esBlogService; @GetMapping("/hi") public Object hello(){ return "helloWorld"; } @GetMapping("/blog/{id}") public Object blog(@PathVariable("id") Long id){ return blogService.getById(id); } @GetMapping("/esBlog/{id}") public Object esBlog(@PathVariable("id") Long id){ return esBlogService.getById(id); } @GetMapping("/search") public Object search(String type,String keyword){ if ((keyword == null || keyword == "") && (type == null || type == "")){ return "请传入参数:?type=es|mysql&keyword={关键字}"; } if (keyword == null || keyword == "") { return "搜索关键字不能为空,参数keyword"; } StopWatch watch = new StopWatch(); HashMap map = new HashMap<>(); watch.start(); if ("es".equals(type)) { map.put("result",esBlogService.searchByKeyword(keyword)) ; }else if ( "mysql".equals(type)){ map.put("result",blogService.searchByKeyword(keyword)) ; }else { map.put("result","查询方式不正确,type = es | mysql") ; } watch.stop(); map.put("time",watch.getTotalTimeMillis()); return map; } } ~~~~ 测试结果,time是花费时间: ~~~~ {"result":[{"id":1,"author":"wang","title":"wang","content":"2q","createTime":"2021-04-19 16:00:00","updateTime":"2021-04-19 16:00:00"}],"time":28} ~~~~