记一次ElasticSearch从安装到使用的过程

背景

最近在写公司官网,发现存在一个搜索功能,本人之前开发还没有使用过es,搜集了各种文章以及ai辅助之后决定出一份完整的从安装到使用的文章,也为方便自己以后再次使用

因本人初学es所以后续发现有问题会及时修正,暂时只研究了怎么使用

公司服务器是虚拟机隔出来的windows系统,因此本文章只会记录windows系统的相关内容

官网项目数据库使用的是mysql,因此需要同步mysql数据到es

ElasticSearch环境准备

下载

ElasticSearch本体:

官网下载需要版本,es自带jdk下哪个版本都可以,本人下载了7.17.28

Kibana:

官网下载,版本必须与es下载的版本一致

LogStash

官网下载,版本也是必须与es一致

Python

python主要用来写生成logstash同步配置文件的脚本

官网下载Miniconda,下载这个主要是不需要python那么多库,只需要安装自己要的即可

环境变量

系统变量添加ES_HOME,ES_JAVA_HOME,LS_HOME,LS_JAVA_HOME

参考:

复制代码
ES_HOME        D:\elasticsearch\elasticsearch-7.17.28
ES_JAVA_HOME   D:\elasticsearch\elasticsearch-7.17.28\jdk
LS_HOME        D:\elasticsearch\logstash-7.17.28
LS_JAVA_HOME   D:\elasticsearch\logstash-7.17.28\jdk

启动

ElashSearch启动,插件安装

  • 进入ElashSearch解压目录,在config目录下修改yml文件内容,添加

    yaml 复制代码
      #开启远程访问 
      network.host: 0.0.0.0
      #单节点模式 初学者建议设置为此模式
      discovery.type: single-node
  • 修改config/jvm.options文件,设置堆内存大小

    复制代码
      -Xms4g
      -Xmx4g
  • 在bin目录下双击bat启动

启动完成访问localhost:9200启动成功,如果是linux系统不允许使用root用户,需设置启动用户

  • 分词插件安装(可选)

在线安装analysis-icu,操作均在bin目录下开启CMD,执行指令即可,ik分词器暂不安装

csharp 复制代码
#查看已安装插件
elasticsearch-plugin list

#安装插件
elasticsearch-plugin install analysis-icu

#删除插件
elasticsearch-plugin remove analysis-icu

Kibana启动

  • 修改config/kibana.yml,添加如下配置

    yaml 复制代码
      server.port: 5601   #指定Kibana服务器监听的端口号
      server.host: "localhost"  #指定Kibana服务器绑定的主机地址
      elasticsearch.hosts: ["http://localhost:9200"]  #指定Kibana连接到的Elasticsearch实例的访问地址
      i18n.locale: "zh-CN"   #将 Kibana 的界面语言设置为简体中文
      
  • 进入bin目录双击bat启动

  • 等待启动完成访问kibana

http://localhost:5601/app/dev_tools#/console

Python编写配置文件

python所需库,需提前安装:mysql-connecter;os

脚本文件内容如下,需修改内容:数据库连接,mysql驱动路径,last_run路径

生成完成的配置文件根据需要删除多余的表

python 复制代码
import mysql.connector
import os

# 数据库配置,请修改对应内容
db_config = {
    'user': '数据库连接用户',
    'password': '数据库连接密码',
    'host': 'localhost',
    'database': '库名',
    'port': 3306
}

# JDBC驱动路径
jdbc_driver_library = r'D:\elasticsearch\mysql-connector-j-9.2.0.jar'

# 连接数据库
conn = mysql.connector.connect(**db_config)

# 清理未读取的结果
while conn.unread_result:
    conn.get_rows()  # 读取并丢弃未读取的结果

cursor = conn.cursor(buffered=True)  # 启用 buffered 模式

# 定义last_run路径
last_run_base_dir = r"D:\elasticsearch\logstash-7.17.28\last_run"
os.makedirs(last_run_base_dir, exist_ok=True)  # 确保目录存在

# 获取所有表名
cursor.execute("SHOW TABLES")
tables = [table[0] for table in cursor.fetchall()]

# 生成 Logstash 配置文件
with open('generated.conf', 'w') as f:
    # 写入 input 部分
    f.write("input {\n")
    for table in tables:
        # 获取主键列名
        cursor.execute(f"""
            SELECT column_name 
            FROM information_schema.key_column_usage 
            WHERE table_schema = '{db_config['database']}' 
            AND table_name = '{table}' 
            AND constraint_name = 'PRIMARY'
        """)
        pk_result = cursor.fetchone()
        if not pk_result:
            print(f"Table {table} has no primary key, skipping...")
            continue
        pk_column = pk_result[0]  # 假设单列主键

        # 写入 jdbc input 配置
        f.write(f"""
          jdbc {{
            jdbc_driver_library => "{jdbc_driver_library}"
            jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
            jdbc_connection_string => "jdbc:mysql://{db_config['host']}:{db_config['port']}/{db_config['database']}?serverTimezone=Asia/Shanghai"
            jdbc_user => "{db_config['user']}"
            jdbc_password => "{db_config['password']}"
            schedule => "* * * * *"
            statement => "SELECT a.{pk_column} AS id, a.*, '{table}' AS table_name FROM {table} a WHERE update_time > :sql_last_value"
            use_column_value => true
            tracking_column => "update_time"
            tracking_column_type => "timestamp"
            last_run_metadata_path => "{os.path.join(last_run_base_dir, f"{table}_metadata")}"
          }}\n""")
        f.write("}\n\n")

        # 写入 filter 部分
        f.write("""
            filter {
              date {
                match => ["update_time", "ISO8601"]
                timezone => "Asia/Shanghai"
              }
              mutate {
                add_field => { "[@metadata][target_index]" => "%{table_name}" }
              }
            }\n\n""")

        # 写入 output 部分
        f.write("""
            output {
              elasticsearch {
                hosts => ["localhost:9200"]
                index => "%{[@metadata][target_index]}"
                document_id => "%{id}"
              }
            }\n""")

cursor.close()
conn.close()

生成的conf文件在LogStash启动时指定,本人移动到了LogStash的config目录下

LogStash启动

mysql驱动包

在maven下载mysql-connector-j,本人下载的最新驱动包9.2.0

放入指定目录,目录需与python脚本所写的目录一致

启动LogStash

在LogStash的bin目录打开cmd

执行指令启动

logstash -f D:\elasticsearch\logstash-7.17.28\configgenerated.conf

执行完后数据将同步到es,后续根据配置文件将一分钟同步一次数据

Kibana设置

点击左上角三横线打开菜单,点击最底下的Stack Management进入管理菜单

点击Kibana下的索引模式,界面内点击创建索引模式,右侧数据为同步的表,每一张表都是一条索引

t_*是我已经创建的索引模式,在查询时将会匹配所有符合的索引进行查询

查询测试:

Springboot接入ES查询数据

引入pom

注意springboot版本,我的是2.5.X,支持7.17.28,具体需参考es官网配置图

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

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

yml配置

js 复制代码
spring:
    elasticsearch:
        uris: http://localhost:9200
        connection-timeout: 3s

创建实体

kotlin 复制代码
import lombok.Data;
import nonapi.io.github.classgraph.json.Id;
import org.springframework.data.elasticsearch.annotations.Document;

@Data
@Document(indexName = "t_*")
public class TJnswTitleElastic {

    @Id
    private Long id;

    private String title;

    private String index;
}

查询

部分代码:

typescript 复制代码
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;

@Override
public List<TJnswTitleElastic> selectTJnswTitleElasticByPkTitle(String title) {
    // 构建查询
    NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.matchQuery("title", title)
                    .minimumShouldMatch("75%"))
            .withSourceFilter(new FetchSourceFilter(new String[]{"title"}, null))
            .withPageable(PageRequest.of(0, 10))
            .build();

    // 执行查询
    SearchHits<TJnswTitleElastic> searchHits = elasticsearchRestTemplate.search(searchQuery, TJnswTitleElastic.class);

    // 提取结果并设置 _index 字段
    return searchHits.stream()
            .map(hit -> {
                TJnswTitleElastic entity = hit.getContent();
                entity.setIndex(hit.getIndex()); // 设置 _index 字段
                return entity;
            })
            .collect(Collectors.toList());
}

查询验证

后记

我发现删除的数据不会被同步,因此所有的表如果涉及删除需要逻辑删除,字段需统一

官网文章存在是否发布的功能,未发布的不可以显示,es又是所有数据同步,搜索时需注意这部分

用logstash自动同步的表在es内不会使用分词插件,会使用es默认的分词

学习之路任重道远,在es上还是起步阶段,共勉

相关推荐
止语Lab2 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活2 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困2 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn2 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
用户298698530142 小时前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
用户77283104908402 小时前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端
Conan在掘金2 小时前
鸿蒙报错速查:Function lacks ending return statement,返回路径漏 return 就炸,根因 + 真解法
后端
人间凡尔赛3 小时前
AI-Native 云原生架构:2026 年从容器编排到智能体编排的范式革命
后端·云原生·架构
IT_陈寒3 小时前
Vue的响应式让我加班到凌晨3点,原来问题出在这
前端·人工智能·后端
卷无止境3 小时前
提升 Python 代码健壮性的方法大盘点
后端·python