本篇主要介绍一下 如何使用 es 来实现高亮查询, 应用场景为我的博客系统的搜索, 以前博客服务器内存不够安装es , 现在换了台服务器 勉强够用 并且把高亮搜索集成了
效果如下:
可以看到实现了标题和短描述的多字段高亮
1.准备工作
使用的版本如下:
elasticsearch 版本: 7.17.5
elasticsearch-rest-high-level-client 客户端工具 : 7.4.2
elasticsearch-analysis-ik-7.17.5 分词器
es的安装以及 分词器插件安装 就不介绍了
2.博客项目集成准备
做一些集成 准备工作 包括依赖准备 配置 等
2.1 pom 依赖配置
由于我的springboot依赖的是 6.8.8 , 所以我需要提升一下版本 ,注意springboot的依赖传递问题
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.4.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.4.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
<exclusions>
<exclusion>
<artifactId>elasticsearch</artifactId>
<groupId>org.elasticsearch</groupId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</exclusion>
</exclusions>
</dependency>
2.2 设置blog_info es 索引
可以通过kibana 或者发送 curl 来创建 索引
curl -XPUT "http://127.0.0.1:9200/blog_info" -H 'Content-Type: application/json' -d'
{
"mappings": {
"properties": {
"blogTitle": {
"type": "text",
"analyzer": "ik_max_word"
},
"blogShortContent": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}'
2.3 配置 es的地址
springboot的 actuator 会对Elasticsearch 进行健康检查 因为检测到引入了 client 包
所以需要设置如下配置, 或者直接关闭健康检查 不建议
spring:
elasticsearch:
rest:
uris: ["http://172.16.225.111:9200"] # 如果不配置
2.4 配置 RestHighLevelClient
@Component
public class RestHighClientConfig {
private RestHighLevelClient client;
@Autowired
//这里可以直接使用 它会读取上面的配置
private RestClientProperties restClientProperties;
@PostConstruct
public void initClient() {
//String[] ips = {"172.16.225.111:9200"};
List<String> ips = restClientProperties.getUris();
HttpHost[] httpHosts = new HttpHost[ips.size()];
for (int i = 0; i < ips.size(); i++) {
httpHosts[i] = HttpHost.create(ips.get(i));
}
RestClientBuilder builder = RestClient.builder(httpHosts);
client = new RestHighLevelClient(builder);
}
public RestHighLevelClient getClient() {
return client;
}
}
2.5 全量刷新文章到 ES
要想查询 肯定要先把文章刷新到 es 中 , 可以提供一个方法一次性刷新
@Override
public void refreshEsAll() {
List<BlogInfo> blogInfos = blogInfoRepository.findAll();
blogInfos.forEach(
blogInfo -> {
IndexRequest request = new IndexRequest();
request.index("blog_info").id(String.valueOf(blogInfo.getId()));
BlogInfoEs blogInfoEs = new BlogInfoEs();
blogInfoEs.setBlogTitle(blogInfo.getBlogTitle());
blogInfoEs.setBlogShortContent(blogInfo.getBlogShortContent());
String jsonStr = gson.toJson(blogInfoEs);
request.source(jsonStr, XContentType.JSON);
try {
//使用上面提供的 client
IndexResponse index = restHighClientConfig.getClient().index(request, RequestOptions.DEFAULT);
log.info("[refreshEsAll index result {}]", index.getResult());
} catch (IOException e) {
e.printStackTrace();
}
});
}
3. 高亮查询
高亮查询就是把匹配到的term 前面添加你设置的 标签 然后返回在 高亮节点里, 可以供前端直接展示
multiMatchQuery
指定多字段查询
highlighter
指定 高亮的pre post 标签, 并且指定 fragmentSize = 20 限制高亮查询的长度
@Override
public List<BlogInfoVo> queryblogfromessearch(String blogTitle) {
List<BlogInfoVo> blogInfoVos = new ArrayList<>();
SearchRequest searchRequest = new SearchRequest("blog_info");
searchRequest.source()
.query(QueryBuilders.multiMatchQuery(blogTitle, "blogTitle", "blogShortContent")
.operator(Operator.OR))
.highlighter(new HighlightBuilder().preTags("<font color='red'>")
.postTags("</font>")
//指定 fragmentSize = 20
.field("blogTitle", 20)
.field("blogShortContent", 20));
SearchResponse response = null;
try {
response = restHighClientConfig.getClient().search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
Optional.ofNullable(response)
.ifPresent(searchResponse -> {
searchResponse
.getHits()
.forEach(p -> {
Long id = Long.valueOf(p.getId());
String jsonStr = p.getSourceAsString();
BlogInfoVo blogInfoVo = gson.fromJson(jsonStr, BlogInfoVo.class);
blogInfoVo.setId(id);
//由于可能会没有匹配到高亮title , 所以需要先把title设置上 供前端展示
blogInfoVo.setBlogHighlightTitle(blogInfoVo.getBlogTitle());
Map<String, HighlightField> highlightFields = p.getHighlightFields();
Assert.notNull(blogInfoVo, "blogInfoVo is not null");
if (!CollectionUtils.isEmpty(highlightFields)) {
HighlightField blogTitleHighlight = highlightFields.get("blogTitle");
if (blogTitleHighlight != null) {
Text[] fragments = blogTitleHighlight.getFragments();
String highlightValue = fragments[0].toString();
blogInfoVo.setBlogHighlightTitle(highlightValue);
}
HighlightField blogShortContentHighlight = highlightFields.get("blogShortContent");
if (blogShortContentHighlight != null) {
Text[] fragments = blogShortContentHighlight.getFragments();
String highlightValue = fragments[0].toString();
//如果匹配到了短描述的高亮 则替换原有的 内容, 如果没有匹配到则正常展示原有的短描述BlogShortContent
blogInfoVo.setBlogShortContent(highlightValue);
}
}
blogInfoVos.add(blogInfoVo);
});
});
return blogInfoVos;
}
4. 前端配置
我前端用的vue 所以在vue中要展示 html 则需要 使用 v-html 标签即可
<div style="overflow:auto;max-height:400px">
<Option
v-for="item in searchList"
:value="item.blogTitle"
:key="item.blogTitle"
>
<div style="width: 300px">
<!--展示标题 -->
<span class="demo-auto-complete-title" v-html="item.blogHighlightTitle" >
</span>
</div>
<div style="width: 300px">
<!--展示短描述 -->
<span class="demo-auto-complete-title_little" v-html="item.blogShortContent" >
</span>
</div>
</Option>
</div>
总结
本篇主要介绍了 ES 高亮查询的一些基本使用方式, 应用场景是自己的博客系统查询, 本篇还是比较简单易懂的, 后续慢慢改进, 最近快过年了 可以稍微打打酱油 祝大家新年快乐!
原文始发于微信公众号(Johnny屋):Elasticsearch 实现博客高亮查询
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/89684.html