ElasticSearch安装在SpringBoot下的使用,Mysql数据同步到ES:包含多表

ElasticSearch安装在SpringBoot下的使用,Mysql数据同步到ES:包含多表

ElasticSearch的下载以及安装

ElasticSearch的官方下载地址https://www.elastic.co/cn/downloads/elasticsearch
官方的下载地址的速度是非常之慢的(想象一下在龟速下载的情况下辛辛苦苦下载了几个小时,就在你快要下载完毕的时候,突然告诉你网络连接失败…WTF)
在这里给大家提供一个国内比较好用的镜像网站
华为国内下载镜像

内容
下载对应的版本直接解压到要放在的目录就可以了

tar -zxvf elasticsearch-7.7.1-linux-x86_64.tar.gz

进入到bin目录下

cd elasticsearch/bin/
 
./elasticsearch

注意:如果你用的是root账户进行启动会报错

can not run elasticsearch as root

ElasticSearch不允许使用root用户启动,解决办法很简单,只需要创建一个新的账户并给权限到ElasticSearch就可以了

useradd admin
passwd admin
chown -R admin:admin /usr/local/elasticsearch/

切换账户

su admin

在bin目录下面再次启动

./elasticsearch

这时候就可以成功访问了如果不成功最大的可能就是服务器内存的问题(es默认的是2G),这时候需要要修改一下自己的内存就可以了

vi ../config/jvm.options

然后修改为:
-Xms600m
-Xmx600m
然后再次启动就可以了,用本地服务访问:localhost:9200即可,如果想要用开放访问地址需要修改配置文件:在ElasticSearch目录下找到config文件然后编辑elasticsearch.yml文件(修改配置之前需要将账户切换为root账户)

su root
vi config/elasticsearch.yml

修改配置为(先把注释放开):
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: [“node-1”,“node-2”]
node.max_local_storang_nodes: 2
然后进行保存,为了安全起见在执行一下
vi /etc/sysctl.conf
在后面增加一行
vm.max_map_count=262144
执行命令:

sysctl -p

然后切换成刚刚创建的账号到bin目录下重新启EelasticSearch

su admin
./elasticsearch

然后访问对应的地址和端口即可(记得看下防火墙端口是否开放)
后台运行命令

./elasticsearch -d

SpringBoot整合ElasticSearch

ElasticSearch的安装以及完毕,看一下在实际开发中es如何运用起来。在pom文件中加入依赖

		<dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.7.1</version>
        </dependency>

        <!--springboot的elasticsearch服务-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
                <!--spring-data-elasticsearch>-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>${
    
    spring-data-elasticsearch.version}</version>
        </dependency>

在pom文件的properties中指定es相关的版本号

    <properties>
        <java.version>1.8</java.version>
        <elasticsearch.version>7.7.1</elasticsearch.version>
        <spring-data-elasticsearch.version>4.0.1.RELEASE</spring-data-elasticsearch.version>
    </properties>

切记版本号要与上一步安装的版本号保持一致!!!
这里是ES官方给出的建议,要结合自己的框架版本号进行选择
在这里插入图片描述
yml配置文件:

#es配置
elastic-search:
  host:
    port: 10.0.2.135:9200
  #    Socket连接超时时间
  socket-timeout: 6000
  #  连接超时时间
  connection-timeout: 3000

java代码部分
配置文件:

package com.template.customknowledge.config;

import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;

import java.time.Duration;

@Configuration
public class ElasticConfig extends AbstractElasticsearchConfiguration {
    
    

    @Value("${elastic-search.host.port}")
    private String hostAndPort;

    @Value("${elastic-search.socket-timeout}")
    private String socketTimeout;

    @Value("${elastic-search.connection-timeout}")
    private String connectionTimeout;

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
    
    
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(hostAndPort)
                .withSocketTimeout(Duration.ofSeconds(Long.parseLong(socketTimeout)))
                .withConnectTimeout(Long.parseLong(connectionTimeout))
                .build();
        return RestClients.create(clientConfiguration).rest();
    }

    @Bean
    public ElasticsearchRestTemplate elasticsearchRestTemplate() throws Exception {
    
    
        return new ElasticsearchRestTemplate(elasticsearchClient());
    }

}

到此可以直接通过注入:ElasticsearchRestTemplate对象进行es操作。

mysql数据同步到es

上面我们以及将ES的环境以及整合环境准备好了,但是es里面并没有数据所以我们需要将数据添加到ES里面然后进行使用

  1. 通过es的操作api将数据通过业务逻辑添加到es中
  2. 当我们有千万级别的数据需要同步到es中的时候很显然通过第一种方法已经不可取了,就算耗费很久的时间将数据通过业务逻辑同步到es中,但是我们的数据都是在实时变化的,这里就不能能通过这个方式实现了。这里我们可以通过Logstash将数据同步到mysql

Logstash是与es配套使用的同期的还有kibana(数据可视化工具)
这里我们主要说明一下Logstash是如何将mysql的数据同步到es中首先我们通过华为云的国内镜像(上面已经提到了)下载与es版本想对应的logstash版本。切记版本号一定要保持一致!!!
下载完毕后与es解压到同一目录然后在Logstash的根目录下面创建一个文件夹,用来存放同步数据的文件

mkdir mysql

然后将数据库的连接jar包放到改文件下面(maven仓库里面有直接拿过来用)
接下来是同步数据的关键:
创建一个sql文件:select *from 需要同步的表名。如果你不想同步所有字段就不用select * ;文件创建完毕以后保存退出。

vim test.sql
select *from 表名

然后在创建一个文件jdbc.conf用来进行同步

vim jdbc.conf

配置文件内容:

input {
    
    
    stdin {
    
    
    }
    jdbc {
    
    
      # mysql 数据库链接,center为数据库名
      jdbc_connection_string => "jdbc:mysql://localhost:1079/project"
      # 用户名和密码
      jdbc_user => "root"
      jdbc_password => "root"
      # 驱动
      jdbc_driver_library => "刚刚存放的数据连接jar的路径"
      # 驱动类名
      jdbc_driver_class => "com.mysql.jdbc.Driver"
      jdbc_paging_enabled => "true"
      jdbc_page_size => "50000"
      # 执行的sql 就是上一步创建的sql文件的绝对路径+文件名字
      statement_filepath => "要同步的表的sql文件路径"
      # 设置监听间隔  各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
      schedule => "* * * * *"
      # 索引类型
      type => "t_01"
    }
filter {
    
    
    json {
    
    
        source => "message"
        remove_field => ["message"]
    }
}
output {
    
    
	elasticsearch {
    
    
    # ES的IP地址及端口
    hosts => ["10.0.2.135:9200"]
    # 索引名称
    index => "t_user"
    # 数据库表所对应的具有唯一标识的字段名称
    document_id => "%{id}"
	}
    stdout {
    
    
       # JSON格式输出
        codec => json_lines
    }
}

从上面的文件中可以看出jdbc.conf配合通过我们指定的要同步的数据同步到es中,配置完毕以后在logstash下的bin文件中运行logstash并指定运行的配置文件

回退到主目录
cd ..
进入bin文件
cd bin
然后运行
./logstash -f ../mysql/jdbc.conf

在这里插入图片描述
运行成功数据开始进行同步到了es,那么问题来了如果是多个表的数据都需要同步到es呢?
多个表的数据同步到es只需要在mysql文件夹下面多些几个sql文件即可然后再重新编写jdbc.conf文件为:

input {
    
    
    stdin {
    
    
    }
    jdbc {
    
    
      # mysql 数据库链接,center为数据库名
      jdbc_connection_string => "jdbc:mysql://10.0.2.135:1079/project"
      # 用户名和密码
      jdbc_user => "root"
      jdbc_password => "112233"
      # 驱动
      jdbc_driver_library => "mysql连接jar包的路径"
      # 驱动类名
      jdbc_driver_class => "com.mysql.jdbc.Driver"
      jdbc_paging_enabled => "true"
      jdbc_page_size => "50000"
      # 执行的sql 就是上一步创建的sql文件的绝对路径+文件名字
      statement_filepath => "对应表1的sql路径"
      # 设置监听间隔  各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
      schedule => "* * * * *"
      # 索引类型
      type => "t_01"
    }
	jdbc {
    
    
      # mysql 数据库链接,center为数据库名
      jdbc_connection_string => "jdbc:mysql://10.0.2.135:1079/project"
      # 用户名和密码
      jdbc_user => "root"
      jdbc_password => "112233"
      # 驱动
      jdbc_driver_library => "mysql连接jar包的路径"
      # 驱动类名
      jdbc_driver_class => "com.mysql.jdbc.Driver"
      jdbc_paging_enabled => "true"
      jdbc_page_size => "50000"
      # 执行的sql 就是上一步创建的sql文件的绝对路径+文件名字
      statement_filepath => "对应表2的路径"
      # 设置监听间隔  各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
      schedule => "* * * * *"
      # 索引类型
      type => "t_02"
    }
}


filter {
    
    
    json {
    
    
        source => "message"
        remove_field => ["message"]
    }
}


output {
    
    
#通过type来进行区分表的数据然后建立索引进行存储
	if[type]=="t_01"{
    
    
		elasticsearch {
    
    
        # ES的IP地址及端口
        hosts => ["10.0.2.135:9200"]
        # 索引名称
        index => "t_user"
        # 自增ID id必须是待查询的数据表的序列字段
        document_id => "%{id}"
		}
	}
	if[type]=="t_02"{
    
    
		elasticsearch {
    
    
        # ES的IP地址及端口
        hosts => ["10.0.2.135:9200"]
        # 索引名称
        index => "t_member"
        # 自增ID id必须是待查询的数据表的序列字段
        document_id => "%{uid}"
		}
	}
    
    stdout {
    
    
       # JSON格式输出
        codec => json_lines
    }
}

ES在springboot中的简单示例

上面我们已经把es的环境以及配置已经数据同步弄好了下面我们简单的使用一下es的操作。
实体类文件:

package com.template.customknowledge;

import lombok.*;


import java.io.Serializable;

import lombok.experimental.Accessors;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Document(indexName = "t_member")
public class MemberInfo implements Serializable {
    
    

    /**
     * uid
     */
    @Field(name = "uid")
    private String uid;

    /**
     * 姓名
     */
    @Field(name = "name")
    private String name;

    /**
     * 年龄
     */
    @Field(name = "age")
    private Integer age;

    /**
     * 创建时间
     */
    @Field(name = "create_time")
    private String createTime;


}

逻辑代码:

package com.template.customknowledge.es;

import com.github.pagehelper.PageInfo;
import com.template.common.common.response.Response;
import com.template.customknowledge.MemberInfo;
import com.template.customknowledge.PosPaymentOrderPo;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;

@RequestMapping("admin")
@RestController
public class EsController {
    
    

    /**
     * BoolQuery( ) 用于组合多个叶子或复合查询子句的默认查询
     * must 相当于 与 & =
     * must not 相当于 非 ~   !=
     * should 相当于 或  |   or
     * filter  过滤
     */

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @RequestMapping("member_search")
    public Response memberSearch() {
    
    
        //BoolQueryBuilder用来组装查询的条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        //组装年龄条件
        RangeQueryBuilder age = QueryBuilders.rangeQuery("age");
        //年龄小于20的
        RangeQueryBuilder lt = age.gte(10).lte(100);
        //组装时间条件
        RangeQueryBuilder createTime = QueryBuilders.rangeQuery("create_time");
        //组装创建时间大于等于"2020-09-16 11:40:27小于等于"2020-09-17 11:40:43"的条件
        RangeQueryBuilder timeRange = createTime
                .format("yyyy-MM-dd HH:mm:ss")
                .gte("2019-09-10 11:40:27")
                .lte("2020-09-20 11:40:43");
        //将组装完的条件用queryBuilder.must()进行组合
        BoolQueryBuilder resultQuery = queryBuilder
                .must(lt)
                .must(timeRange);
        //NativeSearchQueryBuilder用来进行查询的调整比如排序,分页等;
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        NativeSearchQuery nativeSearchQuery = builder
                .withFilter(resultQuery)//关联查询条件
                .withPageable(PageRequest.of(0, 10))//分页条件
                .withSort(SortBuilders.fieldSort("create_time.keyword").order(SortOrder.ASC))
                .build();
        SearchHits<MemberInfo> memberInfoSearchHits = elasticsearchRestTemplate.search(nativeSearchQuery, MemberInfo.class, IndexCoordinates.of("t_member"));
        //获取得到的数据集合
        List<MemberInfo> memberInfos = memberInfoSearchHits.toList().parallelStream().map(SearchHit::getContent).collect(Collectors.toList());
        PageInfo<MemberInfo> pageInfo = new PageInfo<>(memberInfos);
        pageInfo.setTotal(memberInfoSearchHits.getTotalHits());
        return Response.success(pageInfo);
    }
}

然后调用接口得数据:
在这里插入图片描述
数据库中的数据:
在这里插入图片描述

总结

到这里es的环境搭建已经整合springboot在项目中的简单使用示例已经全部搞定啦,es的查询api有很多种,上面弄的都是一些简单的操作,但是万变不离其宗总体的查询思路与mysql很相似,一开始不熟悉不会用很正常多用用就都会了,不练习是不行滴,有任何问题可以在下面留言通知我,大家有没有其他感兴趣的想了解的知识也可以留言通知我,我抽时间整理一下
es整合的代码我会抽时间整理到码云已经github上

猜你喜欢

转载自blog.csdn.net/weixin_42523841/article/details/108647803