Elasticsearch实现站内搜索并与MySQL实时同步

2019-07-20 wjy329 SpringBoot 89

背景:
一开始博客使用了百度的搜索接口,百度的那个接口只能查找你已经被百度收录的内容,博客被收录的很少,而且接口经常有问题,所以不得不自己搞一个站内搜索了。本来想用MySQL的like %keyword%,想想效果就差;然后就想到了大名鼎鼎的Elasticsearch,那咱就搞起来吧。

环境与版本:
CentOS7
SpringBoot 1.5.6
MySQL 5.6
Elasticsearch 6.2.3
Logstash 6.2.3
elasticsearch-analysis-ik 6.2.3
mysql-connector-java-5.1.46.jar

下载地址:

注:我这里所有文件均下载到 /usr/local/src 目录下,后面大家注意路径

安装:
  1. 1.下载完elasticsearch-6.2.3.tar.gz后,用tar -xvf elasticsearch-6.2.3.tar.gz解压后,出现elasticsearch-6.2.3文件夹;
  2. 2.下载完elasticsearch-analysis-ik-6.2.3.zip后,用unzip elasticsearch-analysis-ik-6.2.3.zip解压后,出现elasticsearch文件夹,将elasticsearch文件夹命名为ik或其他,将改为ik的文件夹全部复制到1中elasticsearch-6.2.3/plugins 下即可。
  3. 3.下载完logstash-6.2.3.tar.gz后,用tar -xvf logstash-6.2.3.tar.gz解压后,出现logstash-6.2.3文件夹,将mysql-connector-java-5.1.46.jar包复制到/logstash-6.2.3/logstash-core/lib下,然后在/logstash-6.2.3/bin 下新建一个存放同步配置的文件夹,我这里叫mysql_syn,然后在/logstash-6.2.3/bin/mysql_syn下新建同步配置文件,我起名为jdbc.conf,具体如下:
input {
stdin { }
jdbc {
## mysql-connector-java jar包位置
jdbc_driver_library => "/usr/local/src/logstash-6.2.3/logstash-core/lib/mysql-connector-java-5.1.46.jar"
jdbc_driver_class => "com.mysql.jdbc.Driver"
## 需要同步的数据库连接
jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/blog"
## 数据库用户名
jdbc_user => "root"
## 数据库密码
jdbc_password => "root"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000"
## 查询语句,具体的表即可
statement => "SELECT * FROM article"
schedule => "* * * * *"
}
}

output {
elasticsearch {
hosts => "localhost:9200"
## 索引名称
index => "es"
document_type => "article"
document_id => "%{id}"
}
}
完成上述步骤,其实安装就完成了,接下来只需分别运行Elasticsearch和Logstash即可开启同步;

运行:
  1. 1. 运行Elasticsearch需要切换到非root用户,我这里使用wjy代替,先将Elasticsearch的权限付给wjy,chown -R wjy elasticsearch-6.2.3,切换wjy,su wjy,然后进入elasticsearch-6.2.3/bin ,执行./elasticsearch 即可启动;如有报错百度错误即可;
  2. 2. 执行 cd /usr/local/src/logstash-6.2.3/bin ,执行./logstash -f mysql_syn/jdbc.conf 即可。

这样就会开启实时同步。

在服务器下,需要全部放在后台运行:
./elasticsearch -d 可后台运行Elasticsearch
nohup ./logstash -f ./configs > logstash-out.file 2>&1 & 后台运行Logstash

与SpringBoot整合:
这才是重头戏。
1.依赖
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>

<!-- elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.2.3</version>
</dependency>

<!-- Java High Level REST Client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.2.3</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
</exclusions>
</dependency>
注意版本即可;

2.Elasticsearch配置文件
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
* @Author wjy329
* @Time 2019-07-19 12:36
* @description
*/

@Configuration
public class ElasticConfig {

@Bean
public RestHighLevelClient client() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
return client;
}

}


3.搜索接口实现
先注入:
@Autowired
private RestHighLevelClient client;
然后写实现:
@RequestMapping(value="/search")
public String search(Model model,String keyword,@RequestParam(name="page", required = false) Integer page){
if(page == null){
page = 1;
}

List<JSONObject> result = new ArrayList<>();

//默认显示20条
Integer size = 10;

//search request 这里的es为同步配置文件的索引
SearchRequest searchRequest = new SearchRequest("es");

//search builder
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 在哪个字段中查找关键字
sourceBuilder.query(QueryBuilders.matchQuery("content", keyword));
sourceBuilder.from((page - 1) * size);
sourceBuilder.size(size);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//sort
sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));

//response
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = null;
try {
searchResponse = client.search(searchRequest);
}catch (IOException e){
e.printStackTrace();
}


SearchHits hits = searchResponse.getHits();
//总条数
Integer total = (int)hits.getTotalHits();
// 计算总页数
Integer totalPage;

if (total % size == 0) {
totalPage = total / size;
} else {
totalPage = total / size + 1;
}
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String str = hit.getSourceAsString();
JSONObject articleJson = JSONObject.parseObject(str);
result.add(articleJson);
}

model.addAttribute("total",total);
model.addAttribute("keyword",keyword);
model.addAttribute("currentPage",page);
model.addAttribute("totalPage",totalPage);
model.addAttribute("articleArr",result);

return "blog/search";

}
上面的注释应该比较详细,为了简单明了的理解代码,我都写在了一起,按自己需要进行优化。返回的数据和前台展示按个人喜好设计即可。

这样一个简单的站内搜索就完成了。

效果图:



个人感觉难点还是在安装和运行Elasticsearch和Logstash,总是有错误出现,不过只要耐心查阅总会解决的。这东西真的耗内存基础服务器的配置根本不够用啊,内存爆满!!!

本篇文章仅为个人快速实践,没有详细学习相关知识,如有错误请指出,谢谢。



本文作者:wjy329
版权声明:本博客除特殊说明外均属本人原创。如需转载请署名作者及文章出处。
评论