# 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}
~~~~