主要是想把Elasticsearch整合到当前的系统中,用来搜索文章。
环境
Elasticsearch 7.12.0
Logstash 7.12.0
Mysql 8.0
数据同步
把Elasticsearch整合到现有系统意味需要把当前要搜索的数据添加到Elasticsearch里面,这就有个数据同步问题。因为是测试工程使用的是Logstash的全量数据同步。Logstash的新版本已经包含了Jdbc的插件,所以不需要安装。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| input { jdbc { # myslq驱动,可以官网下载,我用的是Maven依赖已经下载的Jar文件 jdbc_driver_library => "" # Mysql驱动类全类名,注意mysql8.x以上需要加cj jdbc_driver_class => "com.mysql.cj.jdbc.Driver" # mysql连接url jdbc_connection_string => "" # mysql 用户名 jdbc_user => "" # mysql 密码 jdbc_password => "" # 设置定时任务,多久执行一次查询,默认一分钟,需要无延迟可使用schedule => "* * * * * *" schedule => "* * * * *" # 清空上次的sql_last_value记录 clean_run => true # 要执行的sql(同步)语句,替换成你自己的sql statement => "SELECT * FROM t_article" } }
output { elasticsearch { # es主机和端口 hosts => ["127.0.0.1:9200"] # 同步数据在ES的索引名称,替换为你自己的。 index => "my-cms" # es文档的id,表示使用mysql表的id document_id => "%{id}" } }
|
生产环境的数据同步可以参考阿里云Elasticsearch
参考:
Jdbc input plugin
Spring Boot配置
添加Maven依赖
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
|
添加Elasticsearch客户端配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| @Configuration @EnableElasticsearchRepositories(basePackages = "io.pratik.elasticsearch.repositories") @ComponentScan(basePackages = { "io.pratik.elasticsearch" }) public class ElasticsearchClientConfig extends AbstractElasticsearchConfiguration { @Override @Bean public RestHighLevelClient elasticsearchClient() { final ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo("localhost:9200") .build();
return RestClients.create(clientConfiguration).rest(); }
@Bean @Override public EntityMapper entityMapper() {
ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper( elasticsearchMappingContext(), new DefaultConversionService() ); entityMapper.setConversions(elasticsearchCustomConversions());
return entityMapper; } }
|
测试文章类,必须要加type='_doc'
,不然无法使用。另外遇到的问题是我数据库的日期用的是Date
话,一直提示解析错误,最后使用LocalDateTime
后就好了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Data @Document(indexName = "my-cms", type = "_doc") public class EsArticle { @Id private Integer id;
@Field(type = FieldType.Text, analyzer = "ik_max_word") private String title;
@Field(name = "content", type = FieldType.Text, analyzer = "ik_max_word") private String articleContent;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Field(name = "create_time") private LocalDateTime createTime; }
|
创建Repository
类。
1 2 3
| public interface ElasticArticleRepository extends ElasticsearchRepository<EsArticle, Integer> { }
|
生成Controller
,使用Postman测试接口是否正常工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @RestController @RequestMapping("/article") public class SearchController { @Autowired private ElasticArticleRepository elasticRepository;
@PostMapping(value = "/search") public List<EsArticle> handleSearchRequest( @RequestParam Map<String, Object> requestParam) { BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); String keyword = (String) requestParam.get("keyword"); queryBuilder.should(QueryBuilders.matchPhraseQuery("title", keyword)) .should(QueryBuilders.matchPhraseQuery("content", keyword)); StopWatch watch = new StopWatch(); watch.start(); Page<EsArticle> articles = (Page<EsArticle>) elasticRepository.search(queryBuilder); watch.stop(); System.out.println(String.format("数据检索耗时:%s ms", watch.getTotalTimeMillis())); return articles.getContent(); } }
|