一、环境搭建
1.启动ElasticSearch服务器(以7.7.0版为例)
下载地址:https://www.elastic.co/cn/downloads/elasticsearch
访问localhost:9200返回以上信息则表示服务启动成功。
2.启动Kibana
Kibana 下载地址:https://www.elastic.co/cn/downloads/kibana
访问: http://localhost:5601/app/kibana#/home?_g=(),kibana默认会自动连接本地的es服务器。
出现以上的控制台表示kibana启动成功。
点击Dev Tools选项进入开发工具,插入几条测试数据
3.创建一个SpringBoot项目,引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
注意:要特别指定ElasticSearch的版本和依赖的版本一致
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.7.0</elasticsearch.version>
</properties>
4.编写一个ElasticSearch配置类,给容器中添加一个可以访问的es的客户端。
@Configuration
public class ElasticSearchConfig {
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
COMMON_OPTIONS = builder.build();
}
@Bean
public RestHighLevelClient es(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
return client;
}
}
二、实现高亮查询
实现高亮结果的总体思路是:
(1 构建一个检索请求 (SearchRequest)。
(2 构建一个搜索源(SearchSourceBuilder),可以为这个对象添加搜索条件,超时时间,高亮属性等。
(3 构建一个高亮器(HighlightBuilder),为其指定高亮的属性以及前缀和后缀等,例如想让 “”西红柿“”这三个字高亮显示,就可以为这个关键词加前缀<span style="color:red">
,后缀</span>
。这样整个结果就是<span style="color:red">西红柿</span>
,将来再通过html网页解析就可以实现结果高亮。
(4 为SearchRequest设置SearchSourceBuilder,执行检索,返回SearchResponse。
(5 拿到SearchResponse中的hits的hits,遍历这个hits数组,拿到之前设置的高亮字段进行拼接,再讲拼接好的值替换旧的值。
实例代码如下:
@Service
public class ESProductService {
@Autowired
private RestHighLevelClient client;
public List<ESProductTO> searchProduct(String keywords) throws IOException {
List<ESProductTO> esProductTOS = new ArrayList<>();
//1.构建检索条件
SearchRequest searchRequest = new SearchRequest();
//2.指定要检索的索引库
searchRequest.indices("product");
//3.指定检索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
sourceBuilder.query(QueryBuilders.multiMatchQuery(keywords,"productName"));
//4.结果高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(true); //如果该属性中有多个关键字 则都高亮
highlightBuilder.field("productName");
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
sourceBuilder.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
SearchResponse response = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);
SearchHit[] hits = response.getHits().getHits();
for (SearchHit hit : hits) {
//如果不做高亮,则可以直接转为json,然后转为对象
// String value = hit.getSourceAsString();
// ESProductTO esProductTO = JSON.parseObject(value, ESProductTO.class);
//解析高亮字段
//获取当前命中的对象的高亮的字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField productName = highlightFields.get("productName");
String newName = "";
if (productName != null){
//获取该高亮字段的高亮信息
Text[] fragments = productName.getFragments();
//将前缀、关键词、后缀进行拼接
for (Text fragment : fragments) {
newName += fragment;
}
}
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//将高亮后的值替换掉旧值
sourceAsMap.put("productName",newName);
String json = JSON.toJSONString(sourceAsMap);
ESProductTO esProductTO = JSON.parseObject(json, ESProductTO.class);
esProductTOS.add(esProductTO);
}
return esProductTOS;
}
}
编写测试代码:
@Autowired
private ESProductService esProductService;
@Test
public void testSearchHighLight() throws IOException {
List<ESProductTO> products = esProductService.searchProduct("面");
for (ESProductTO product : products) {
log.info(product.toString());
}
}
日志查看:
可以看到,我们搜索的关键字 “面” 已经被高亮了!