我们在搜索某篇文章或者是博客时,如果想要更快的找到做自己想要查找的数据,很多时候可以采用高亮显示来突出我们需要查询的关键词,就好比在淘宝上购买商品,查询出来的数据可以高亮显示我们需要查询的关键词,如下图所示:
在上图中,我们通过搜索关键词"五常大米",在搜索的结果中,我们可以看到搜索的结果中,关键词 五常 和 大米 都被高亮展示了,在搜索结果集中我们可以清楚的看到我们的搜索行为,给用户带来细节上的体验;
那么,下面通过一个简单的java案例来实现对搜索关键词的一个高亮显示吧(如果理解了分词器的原理就更好了);
我这边程序中使用的是Elasticsearch7.8.0版本,配置的IK分词器,采用的是IK默认的分词词库以及额外配置了远程扩展词库;
直接上核心代码吧;
private Json queryConditionExtract(int pageSize) {
// 构建查询请求 及 封装查询语句 ....代码略....
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 是否开启高亮显示
if (form.isHighlighted()) {
HighlightBuilder highlightBuilder = new HighlightBuilder();
//高亮的字段
highlightBuilder.field("goodsInfoName");
//是否多个字段都高亮
highlightBuilder.requireFieldMatch(false);
//前缀后缀
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
sourceBuilder.highlighter(highlightBuilder);
}
// 执行查询 ....代码略....
SearchResponse myresponse = client.search(new SearchRequest(indexName).source(sourceBuilder), RequestOptions.DEFAULT);复制
在上述代码中,首先构建查询请求以及封装请求数据,然后对指定查询字段进行高亮设置,对高亮词组设置高亮属性,比如 字体加粗、改变颜色等属性,然后封装到请求中,执行查询语句,获取查询结果集;
拿到查询结果集后,可以开始进行对查询结果集的解析,代码如下
SearchHits hits = myresponse.getHits();
log.info("本次商品查询到 {} 条结果 ; 本次查询最大匹配度max_score为: {}", hits.getTotalHits(), hits.getMaxScore());
// 定义返回结果集的封装
List list = new ArrayList<EsSelectGoodsVo>();
for (SearchHit hit : hits) {
if (form.isHighlighted()) {
//解析高亮的字段,获取高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField content = highlightFields.get("goodsInfoName");
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//将原来的字段替换为高亮字段即可
if (content != null) {
Text[] fragments = content.fragments();
String newTitle = "";
for (Text text : fragments) {
newTitle += text;
}
//替换掉原来的内容
sourceAsMap.put("goodsInfoName", newTitle);
}
list.add(JSONObject.parseObject(JSONObject.toJSONString(sourceAsMap), EsSelectGoodsVo.class));
}else {
list.add(JSONObject.parseObject(hit.getSourceAsString(), EsSelectGoodsVo.class) );
}
}
return ...略 对查询到的结果集的处理复制
return ...略 对查询到的结果集的处理复制
在上述代码中,是对查询结果集的处理;上面代码从查询结果集中获取所有需要呈现高亮显示的字段(当配置了多个需要高亮显示的字段时),然后获取我们设置的需要高亮显示的字段,将原来的查询分词字段替换成高亮显示的字段,然后再赋值回去;
这样就拿到了我们需要展示的数据;这里我采用的查询关键词为:"五常大米",ik分词器分词后为 五常 和 大米;
最后拿到的数据如下所示(示例,其他字段已删除):
{
"goodsInfoName": "金龙鱼<span style='color:red'>五常</span>基地原香稻5KG/袋 东北<span style='color:red'>大米</span> 香软可口(5KG)"
}复制
可以看到,在搜索的关键词分词后的词组,五常 和 大米 都被打上了css标签,当呈现到前端展示的时候,就可以呈现出高亮展示的效果了;
那么,看一下最终都实现效果吧;是不是跟淘宝有一点点小相似~ 就是不知道为什么有时候名称中的一些数字,也会被标记红色.....
再来看一下DSL的执行语句:
在DSL语句中,可以看到在后面加了一个条件highight,里面指定了条件以及高亮规则等;