接 ElasticSearch服务集群搭建以及应用(三)
一:SpringBoot集成ES集群查询设置
1.配置三个ES服务的elasticsearch.yml文件,并启动三个服务
2.配置logstash下的config目录下配置mysql.conf文件,打开集群配置
3.logstash的工作是从MySQL中读取数据,向ES中创建索引,这里需要提前创建mapping的模板文件以便logstash 使用。
{
"mappings" : {
"es_course" : {
"properties" : {
"course_name" : {
"analyzer" : "ik_max_word",
"search_analyzer":"ik_smart",
"type" : "text"
},
"course_description" : {
"analyzer" : "ik_max_word",
"search_analyzer":"ik_smart",
"type" : "text"
},
"id" : {
"type" : "keyword"
},
"course_pic" : {
"index" : false,
"type" : "keyword"
}
}
}
},
"template" : "es_course"
}
4.使用head新建集群索引es_course,分片3,副本2并使用postman添加映射关系
5.在logstash的bin目录下,启动logstash
logstash.bat ‐f …/config/mysql.conf6.启动成功之后,会看到mysql数据库数据被导入到ES,如下
二:SpringBoot集成ES集群查询编码
我们最终的目的是在项目中引用ES的服务 , 实现业务中使用ES索引库实现查询的功能
1.在工程的pom文件里面引入ES相关的jar 6.2.1版本如下:
<!--引入ES-->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.2.1</version>
</dependency>
<!--引入ES相关API的高级客户端-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.2.1</version>
</dependency>
<!--引入ES相关API的低级客户端-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.2.1</version>
</dependency>
2.创建工具类,用来解析ES集群的IP和端口,获取高级客户端对象
@Configuration
public class ESSearchUtil {
@Value("${elasticsearch.hostlist}")
private String hostlist;
/**
* @description : 获取ES高级客户端对象
* @Date 2020/11/18
* @Param []
* @return org.elasticsearch.client.RestHighLevelClient
*/
@Bean
public RestHighLevelClient restHighLevelClient(){
String[] split = hostlist.split(",");//解析ES集群IP端口信息
HttpHost[] httpHostArray = new HttpHost[split.length];//创建HttpHost数组,其中存放es主机和端口的配置信息
for (int i = 0; i < split.length; i++) {
String item = split[i];
httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
}
return new RestHighLevelClient(RestClient.builder(httpHostArray));//创建RestHighLevelClient客户端
}
/**
* @description : 获取ES低级客户端对象
* @Date 2020/11/18
* @Param []
* @return org.elasticsearch.client.RestClient
*/
@Bean
public RestClient restClient(){
String[] split = hostlist.split(",");//解析ES集群IP端口信息
HttpHost[] httpHostArray = new HttpHost[split.length];//创建HttpHost数组,其中存放es主机和端口的配置信息
for(int i=0;i<split.length;i++){
String item = split[i];
httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":") [1]), "http");
}
return RestClient.builder(httpHostArray).build();
}
}
3.配置application.yml,如下
elasticsearch:
hostlist: ${eshostlist:127.0.0.1:9200,127.0.0.1:9201,127.0.0.1:9202}
course:
index: es_course
type: doc
source_field:
id,course_name,course_description #过滤字段,即不需要查询的字段,我们这里选择保留id,course_name,course_description这几个字段,用逗号隔开
4.创建接口,根据分页参数(page,size)以及对于course_name和course_description进行关键字搜索
@Controller
@RequestMapping("api/es")
public class ESSearchController {
@Autowired
private ESService esService;
/**
* @description : 按请求的条件从ES索引库中进行分页查询
* @Date 2020/11/18
* @Param [page, size, request]
* @return com.example.common.response.R<com.example.service.es.model.CoursePub>
*/
@RequestMapping("/list")
@ResponseBody
public R list(@RequestBody CourseSearchRequest request){
Page<CoursePub> pubPage = esService.list(request);
if(pubPage!=null){
return R.ok(pubPage);
}
return R.error("未获取到相关数据");
}
}
@Data
public class CourseSearchRequest {
private Integer page;//页码
private Integer size;//每页条数
private String keyword;//按关键字查询
}
5.实现类中具体实现的代码如下:
@Service
@Slf4j
public class ESServiceImpl implements ESService {
@Value("${elasticsearch.course.index}")
private String index;
@Value("${elasticsearch.course.type}")
private String type;
@Value("${elasticsearch.course.source_field}")
private String source_field;
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* @description : 按请求的条件从ES索引库中进行分页查询
* @Date 2020/11/18
* @Param [page, size, request]
* @return com.example.common.page.Page<com.example.service.es.model.CoursePub>
*/
public Page<CoursePub> list(CourseSearchRequest request){
Page<CoursePub> pubPage=new Page<>();
SearchRequest searchRequest=new SearchRequest(index);//创建搜索请求对象,括号里给索引库名称
searchRequest.types(type);//设置索引库的类型
SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
//创建布尔查询字段
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//source_field字段过滤
String[] source_field_array = source_field.split(",");
searchSourceBuilder.fetchSource(source_field_array,new String[]{});
//关键字查询,按"course_name", "course_description"两个字段进行关键字的索引
if(!StringUtil.isEmptyString(request.getKeyword())){
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(request.getKeyword(), "course_name", "course_description");
multiMatchQueryBuilder.minimumShouldMatch("70%");//设置匹配占比70%
multiMatchQueryBuilder.field("course_name",10);//course_name字段匹配度比其他字段高10倍
boolQueryBuilder.must(multiMatchQueryBuilder);
}
//分页
int page=request.getPage();
int size=request.getSize();
if(page<=0){ page = 1; }
if(size<=0){ size = 20; }
int start = (page-1)*size;
searchSourceBuilder.from(start);
searchSourceBuilder.size(size);
//设置布尔查询boolQueryBuilder到searchSourceBuilder
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response=null;
try {
//执行搜索
response = restHighLevelClient.search(searchRequest);
} catch (IOException e) {
e.printStackTrace();
log.info("查询数据有误...");
return pubPage;
}
//获取响应结果
SearchHits hits = response.getHits();
pubPage.setCurrentPage(page);//当前页码
pubPage.setPageSize(size);//页面大小
pubPage.setTotal(hits.getTotalHits());//总记录数
List<CoursePub> list=new ArrayList<>();
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
CoursePub pub=new CoursePub();
Map<String, Object> map = hit.getSourceAsMap();
String id = (String) map.get("id");//获取id
String courseName= (String) map.get("course_name");
String courseDescription= (String) map.get("course_description");
pub.setId(id);
pub.setCourseName(courseName);
pub.setCourseDescription(courseDescription);
list.add(pub);
}
pubPage.setList(list);
return pubPage;
}
}
6.接口测试请求如下
{
"code": "0000",
"msg": "成功",
"data": {
"currentPage": 1,
"pageSize": 10,
"pages": 0,
"total": 6,
"list": [
{
"id": "1",
"courseName": "JAVA基础",
"courseDescription": "JAVA基础是学好JAVA语言的核心,面向对象,多线程等",
"courseTime": null,
"coursePic": null
},
{
"id": "4",
"courseName": "JAVA单列集合",
"courseDescription": "JAVA单列集合包括list接口和set接口,底下分别有实现类",
"courseTime": null,
"coursePic": null
},
{
"id": "5",
"courseName": "JAVA双列集合",
"courseDescription": "JAVA双列集合包括map接口,底下分别有实现类",
"courseTime": null,
"coursePic": null
},
{
"id": "6",
"courseName": "JAVA数据结构",
"courseDescription": "数据结构包含栈,队列,数组,链表,红黑树",
"courseTime": null,
"coursePic": null
},
{
"id": "8",
"courseName": "JAVA面向对象三大特性",
"courseDescription": "封装 继承 多态",
"courseTime": null,
"coursePic": null
},
{
"id": "9",
"courseName": "JAVA常用的设计模式",
"courseDescription": "单例模式:就是将构造方法私有化,分为直接加载和懒加载\r\n\t工厂模式:分为简单工厂模式(根据传递的参数创建指定对象),工厂方法模式(在方法里面创建对象),抽象工厂(接口中定义不同的抽象方法创建对象)模式\r\n\t观察者模式:就是发布订阅模式,订阅即可收到消息,如activeMQ的消息队列\r\n\t代理模式:通过代理对象访问目标对象,如动态代理技术",
"courseTime": null,
"coursePic": null
}
]
}
}