3.5 按难度等级搜索
3.5.1 需求分析
用户选择不同的课程难度等级去搜索课程。
3.5.2 API方法
使用 search_course方法完成搜索。
3.5.3页面
按难度等级搜索思路如下:
1)点击难度等级立即更改路由。
2)通过监听路由,路由更改则立即执行search搜索方法。
按难度等级搜索页面代码如下:
<ul>
<li>难度等级:</li>
<li v‐if="grade!=''">
<nuxt‐link class="title‐link" :to="'/course/search?keyword='+keyword+'&mt=' +
mt+'&st='+st+'&grade='">全部
</nuxt‐link>
</li>
<li class="all" v‐else>全部</li>
<ol>
<li v‐if="grade=='200001'" class="all">初级</li>
<li v‐else><nuxt‐link class="title‐link" :to="'/course/search?keyword='+keyword+'&mt=' +
mt+'&st='+st+'&grade=200001'">初级</nuxt‐link></li>
<li v‐if="grade=='200002'" class="all">中级</li>
<li v‐else><nuxt‐link class="title‐link" :to="'/course/search?keyword='+keyword+'&mt=' +
mt+'&st='+st+'&grade=200002'">中级</nuxt‐link></li>
<li v‐if="grade=='200003'" class="all">高级</li>
<li v‐else><nuxt‐link class="title‐link" :to="'/course/search?keyword='+keyword+'&mt=' +
mt+'&st='+st+'&grade=200003'">高级</nuxt‐link></li>
</ol>
</ul>
3.6 高亮显示
3.6.1 服务端代码
修改service的搜索方法,添加高亮设置:
...
//定义高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<font class='eslight'>");
highlightBuilder.postTags("</font>");
highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
searchSourceBuilder.highlighter(highlightBuilder);
...
//解析高亮字段
for(SearchHit hit:searchHits){
CoursePub coursePub = new CoursePub();
//源文档
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//课程id
String id = (String) sourceAsMap.get("id");
coursePub.setId(id);
//取出name
String name = (String) sourceAsMap.get("name");
//取出高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if(highlightFields.get("name")!=null){
HighlightField highlightField = highlightFields.get("name");
Text[] fragments = highlightField.fragments();
StringBuffer stringBuffer = new StringBuffer();
for(Text text:fragments){
stringBuffer.append(text);
}
name = stringBuffer.toString();
}
coursePub.setName(name);
....
代码如下:
package com.xuecheng.search.service;
import com.xuecheng.framework.domain.course.CoursePub;
import com.xuecheng.framework.domain.search.CourseSearchParam;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author Administrator
* @version 1.0
**/
@Service
public class EsCourseService {
@Value("${xuecheng.course.index}")
private String index;
@Value("${xuecheng.course.type}")
private String type;
@Value("${xuecheng.course.source_field}")
private String source_field;
@Autowired
RestHighLevelClient restHighLevelClient;
//课程搜索
public QueryResponseResult<CoursePub> list(int page, int size, CourseSearchParam courseSearchParam) {
if(courseSearchParam == null){
courseSearchParam = new CourseSearchParam();
}
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest(index);
//设置搜索类型
searchRequest.types(type);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//过虑源字段
String[] source_field_array = source_field.split(",");
searchSourceBuilder.fetchSource(source_field_array,new String[]{});
//创建布尔查询对象
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//搜索条件
//根据关键字搜索
if(StringUtils.isNotEmpty(courseSearchParam.getKeyword())){
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(courseSearchParam.getKeyword(), "name", "description", "teachplan")
.minimumShouldMatch("70%")
.field("name", 10);
boolQueryBuilder.must(multiMatchQueryBuilder);
}
if(StringUtils.isNotEmpty(courseSearchParam.getMt())){
//根据一级分类
boolQueryBuilder.filter(QueryBuilders.termQuery("mt",courseSearchParam.getMt()));
}
if(StringUtils.isNotEmpty(courseSearchParam.getSt())){
//根据二级分类
boolQueryBuilder.filter(QueryBuilders.termQuery("st",courseSearchParam.getSt()));
}
if(StringUtils.isNotEmpty(courseSearchParam.getGrade())){
//根据难度等级
boolQueryBuilder.filter(QueryBuilders.termQuery("grade",courseSearchParam.getGrade()));
}
//设置boolQueryBuilder到searchSourceBuilder
searchSourceBuilder.query(boolQueryBuilder);
//设置分页参数
if(page<=0){
page = 1;
}
if(size<=0){
size = 12;
}
//起始记录下标
int from = (page-1)*size;
searchSourceBuilder.from(from);
searchSourceBuilder.size(size);
//设置高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<font class='eslight'>");
highlightBuilder.postTags("</font>");
//设置高亮字段
highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
searchSourceBuilder.highlighter(highlightBuilder);
searchRequest.source(searchSourceBuilder);
QueryResult<CoursePub> queryResult = new QueryResult();
List<CoursePub> list = new ArrayList<>();
try {
//执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
//获取响应结果
SearchHits hits = searchResponse.getHits();
//匹配的总记录数
long totalHits = hits.totalHits;
queryResult.setTotal(totalHits);
SearchHit[] searchHits = hits.getHits();
for(SearchHit hit:searchHits){
CoursePub coursePub = new CoursePub();
//源文档
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//取出id
String id = (String)sourceAsMap.get("id");
coursePub.setId(id);
//取出name
String name = (String) sourceAsMap.get("name");
//取出高亮字段name
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if(highlightFields!=null){
HighlightField highlightFieldName = highlightFields.get("name");
if(highlightFieldName!=null){
Text[] fragments = highlightFieldName.fragments();
StringBuffer stringBuffer = new StringBuffer();
for(Text text:fragments){
stringBuffer.append(text);
}
name = stringBuffer.toString();
}
}
coursePub.setName(name);
//图片
String pic = (String) sourceAsMap.get("pic");
coursePub.setPic(pic);
//价格
Double price = null;
try {
if(sourceAsMap.get("price")!=null ){
price = (Double) sourceAsMap.get("price");
}
} catch (Exception e) {
e.printStackTrace();
}
coursePub.setPrice(price);
//旧价格
Double price_old = null;
try {
if(sourceAsMap.get("price_old")!=null ){
price_old = (Double) sourceAsMap.get("price_old");
}
} catch (Exception e) {
e.printStackTrace();
}
coursePub.setPrice_old(price_old);
//将coursePub对象放入list
list.add(coursePub);
}
} catch (IOException e) {
e.printStackTrace();
}
queryResult.setList(list);
QueryResponseResult<CoursePub> queryResponseResult = new QueryResponseResult<CoursePub>(CommonCode.SUCCESS,queryResult);
return queryResponseResult;
}
}
3.6.2 前端代码
在search/index.vue中定义eslight样式:
.eslight{
color: #990000;
}
测试