夫天地者,万物之逆旅;光阴者,百代之过客。而浮生若梦,为欢几何?
ElasticSearch全文检索功能实践

前言

ELK即:ElasticSearch + logstash + kibana,(概念性的讲解可自行百度),本文主要学习分享一下如何使用它们来实现站内搜索的功能。实际应用于 知识库项目的全文检索功能。即需要将Oracle中需要被检索的表数据通过logstash同步到ES(下面都说成ES),然后使用ES的restful API来实现搜索的功能。

环境搭建与软件安装

此次主要需要安装如下软件

使用ELK之前,需要先安装jdk和node,安装步骤可自行处理,安装后可查看是否安装成功

安装ElasticSearch

解压后进入ES的bin目录,直接双击运行elasticsearch的批处理文件

看到如下信息时,说明ES已经运行成功

此时,即可打开浏览器,输入:localhost:9200即可查看运行状态

安装ElasticSearch-head插件

下载并解压head插件后,进入head文件夹,执行命令:npm install(此处是为了安装pathomjs);

安装完成之后,执行命令:npm run start或grunt server(grunt:一个很方便的构建工具,需安装:npm install -g grunt-cli),启动head插件

此时,我们再次打开浏览器,输入: localhost:9100,即可看到如下可视化界面

但此时,集群健康值显示未连接状态,这是由于9100和9200之间尚未建立通信,属于跨域访问。此时需要修改es的配置文件,允许跨域访问,即如下:

重启es和head插件后,运行后效果如下

其它机器访问

以上步骤都是在服务器上操作,若需要在我本地的电脑上访问上述的页面,我们直接输入 服务器的IP地址+9100(或9200端口),此时会发现9200端口是无法访问的,因为9200端口被限制为本机访问,因此还需要在elasticsearch.yml配置文件中增加如下配置

此时再次重启es,可能会出现黑窗口闪退的情况,查看es的log日志,会找到如下的报错信息

解决方法

同样需要修改es的yml配置文件,如下:

至此,就完成了es的相关配置,同时在本机也可以访问服务器上的es服务

Oracle数据同步到ES

这里将采用两种方式同步,即:

1、直接将Oracle中的数据同步到es(优点:直接与Oracle交互,保证数据一致性;缺点:每间隔XX时间就会查询数据库一次,DB开销较大);

2、文章的insert、delete和update的操作时,先将数据推送到MQ,再将MQ的数据同步到es(优点:避免与Oracle多次交互,解耦的同时也减少数据库开销;缺点:后期维护成本较大,若MQ服务出现问题,会导致数据不一致)。

针对这两种方式,我们都将使用一个数据同步的中间件:Logstash.(当然、如果不使用logstash的话,也可以自己写一个Windows服务,定时同步Oracle中的数据,或实时监听并消费MQ中的消息,以实现数据同步的目的)

安装配置logstash

使用logstash同步Oracle时,需要用到ojdbc的jar包,因此需要下载并放到指定的目录,作者放到如下位置

接下来就是配置同步相关的内容,我们找到如下文件

下面直接贴上配置内容

同步Oracle

# Sample Logstash configuration for creating a simple
# Beats -> Logstash -> Elasticsearch pipeline.
input {
  jdbc {
        # 数据库连接方式
        jdbc_connection_string => "jdbc:oracle:thin:@127.0.0.1:1521:db"
        # 数据库用户名
        jdbc_user => "user"
        # 数据库密码
        jdbc_password => "password"
        # 此处遇到坑
        jdbc_driver_library => "D:\software\ElasticSearch\logstash-7.13.2\logstash-core\lib\jars\ojdbc6.jar"
        # 数据库驱动器;
        jdbc_driver_class => "Java::oracle.jdbc.driver.OracleDriver"
        # 数据库重连尝试次数
        connection_retry_attempts => "3"
        # 判断数据库连接是否可用,默认false不开启
        jdbc_validate_connection => "true"
        # 数据库连接可用校验超时时间,默认3600s
        jdbc_validation_timeout => "3600"
        #分页可自选
        #jdbc_paging_enabled => "true"
        #jdbc_page_size => "50000"
        # 是否记录上次执行结果, 如果为真,将会把上次执行到的 tracking_column 字段的值记录下来,保存到 last_run_metadata_path 指定的文件中
        record_last_run => "true"
        # 是否需要记录某个column 的值,如果record_last_run为真,可以自定义我们需要 track 的 column 名称,此时该参数就要为 true. 否则默认 track 的是 timestamp 的值
        use_column_value => "true"
        #记录的字段(这里一定要小写)
        tracking_column => "updatetime"
        #记录字段的数据类型
        tracking_column_type => "timestamp"
        #记录字段的文件位置和名称
        last_run_metadata_path => "D:\software\ElasticSearch\logstash-7.13.2\sql\jdbc_oracle_lastvalue.txt"
        # 是否清除 last_run_metadata_path 的记录,如果为真那么每次都相当于从头开始查询所有的数据库记录
        clean_run => "false"
        #要执行的sql文件位置
        statement_filepath =>"D:\software\ElasticSearch\logstash-7.13.2\sql\jdbc_oracle.sql"
        #定时执行
        #schedule => "* * * * *"
        #之前的写法是 "* * * * *",现在在前面再加一个,为2秒刷新一次,默认每分钟同步一次
        schedule => "*/2 * * * * *"
        #时区
        jdbc_default_timezone =>"Asia/Shanghai"
  }
}
output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
    index => "indexname"
    # 数据唯一索引(建议同数据库表的唯一ID对应)
    document_id => "%{id}"
    #index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
    #user => "elastic"
    #password => "changeme"
  }
}

同步RabbitMQ

# Sample Logstash configuration for creating a simple
# Beats -> Logstash -> Elasticsearch pipeline.
input {
  rabbitmq{
host=>"127.0.0.1"                             # 这里填写Rabbitmq的地址,确保可以ping通
port=> 5672                            # 这里填写Rabbitmq的端口
user=>"user"                          # 这里填写Rabbitmq的用户名
password=>"password"                      # 这里填写Rabbitmq的密码
queue=>"queuename"              # 这里填写Rabbitmq的队列的名称
durable=> true                         # 这里填写Rabbitmq的队列的durable属性
codec=>json                            # 这里填写Rabbitmq的队列的内容是什么格式
#type=> "result"                        # 这里选填
  }
}
filter
{
mutate
{
      add_field => { "@data" => "%{Data}" } #先新建一个新的字段,并将Data赋值给它
remove_field => ["ServiceMark","AppKey","MsgDate","MsgID"] #删除不必要的字段
    }
json
{
source => "@data"#再进行解析
remove_field => ["@data"]
}
}
output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
    index => "indexname"
    # 数据唯一索引(建议同数据库表的唯一ID对应)
    document_id => "%{id}"
    #index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
    #user => "elastic"
    #password => "changeme"
  }
}

配置并保存后,进入到logstash的bin目录下,执行如下命令,即可等待数据的同步:

logstash -f ../config/logstash-sample.conf
logstash -f ../config/logstash-mq.conf

当看到输出事先写好的sql语句时,即说明数据已经同步到了es中

此时在head插件页面中,就可以看到已经同步到的数据:

到这里,数据同步的工作就大功告成了。接下来使用es的API来实现搜索等功能。具体接口实现这里不做细讲,默认已经写好接口,下面可以通过postman来测试接口使用正确

此时,前端页面就可以调用我们写好的API来搜索并展示数据了。

总结

本文主要学习使用了ElasticSearch和Logstash,以及如何将Oracle和MQ的数据同步到ES,并实现调用接口来实现全文检索(支持高亮显示)的功能。过程中踩了不少坑,最后还需要注意的是,在使用ELK相关套件时,版本需要选择一致。本文使用的版本均为:7.13.2(或者都是 7.x系列,最好选择同一版本),如果ELK的版本选择不一致,可能会出现意想不到的错误信息

相关下载资料

ElasticSearch:https://www.elastic.co/cn/downloads/elasticsearch

Logstash:https://www.elastic.co/cn/downloads/logstash

Kibana:https://www.elastic.co/cn/downloads/kibana

ik分词器:https://github.com/medcl/elasticsearch-analysis-ik/releases




作者:一蓑烟雨

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

1

支持

0

反对

posted @2021-7-26  拜读(380)

评论列表

评论内容:



喜欢请打赏

支付宝 微信

请放心支付