用elastic search实现高亮搜索
前提条件:springboot版本 2.1.6。
·
前提条件:
elastic search 6.5.0
springboot版本 2.1.6
1.导入依赖
<!--elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.配置类
Spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 127.0.0.1:9300
3.将数据库的数据导入elasticsearch
启动elasticsearch6.5.0
在需要创建索引的实体类上加上注解
@Document(indexName = "course", shards = 2,replicas = 0)
加完重启项目,查看es图形化界面就可以看到创建的索引了
4.给索引添加数据
首先编写从数据库获取数据的接口,
/**
* 获取所有课程信息(es渲染页面)
* @return
*/
@GetMapping("list")
public PageInfo<CourseDTO> list(Integer pageNum, Integer pageSize) {
return courseService.getList(pageNum, pageSize);
}
@Repository
public interface ElasticSearchRepository extends ElasticsearchRepository<CourseDTO,Integer> {
}
@Override
public PageInfo<CourseDTO> getList(Integer pageNum, Integer pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<CourseDTO> list = courseMapper.getList();
return new PageInfo<>(list);
}
补充:PageHelper是一个分页的工具类
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version>
</dependency>
@Select("select c.*,t.teacher_name,t.position from course c\n" +
"left join teacher t\n" +
"on c.id = t.course_id")
List<CourseDTO> getList();
在测试接口可以使用后,编写一个接口ElasticSearchRepository 可以改成别的名字重要的是继承
@Repository
public interface ElasticSearchRepository extends ElasticsearchRepository<CourseDTO,Integer> {
}
在测试类中注入mapper层和ElasticSearchRepository ,从数据库获取数据再保存到es中
@RunWith(SpringRunner.class)
@SpringBootTest(classes = CourseApplication.class)
public class EsTest {
@Autowired
private CourseMapper courseMapper;
@Autowired
private ElasticSearchRepository elasticSearchRepository;
@Test
public void createCourse(){
elasticSearchRepository.saveAll(courseMapper.getList());
}
}
然后再次查看es就发现数据保存到esl了
4.接下来就是编写搜索的方法
高亮工具类
public class ElasticsearchUtil {
public static void highlightKeywords(Iterable<CourseDTO> courses, String key) {
// 使用正则表达式进行不区分大小写的匹配
String highlightedKey = "<span style='color:red;'>" + key + "</span>";
String regex = "(?i)" + Pattern.quote(key); // (?i) 表示不区分大小写
Pattern pattern = Pattern.compile(regex);
for (CourseDTO course : courses) {
Matcher matcherCourseName = pattern.matcher(course.getCourseName());
Matcher matcherBrief = pattern.matcher(course.getBrief());
Matcher matcherTeacherName = pattern.matcher(course.getTeacherName());
course.setCourseName(matcherCourseName.replaceAll(highlightedKey));
course.setBrief(matcherBrief.replaceAll(highlightedKey));
course.setTeacherName(matcherTeacherName.replaceAll(highlightedKey));
}
}
}
编写搜索接口
/**
*搜索course
* @param searchDTO
* @return
*/
@GetMapping("search")
public PageImpl<CourseDTO> getCourseByPage(SearchDTO searchDTO){
return courseService.getCourseByPage(searchDTO);
}
PageImpl<CourseDTO> getCourseByPage(SearchDTO searchDTO);
@Resource
private ElasticsearchTemplate elasticsearchTemplate;
@Override
public PageImpl<CourseDTO> getCourseByPage(SearchDTO searchDTO) {
// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 添加范围查询
if (searchDTO.getMinPrice() != 0 || searchDTO.getMaxPrice() != 0) {
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("discounts");
if (searchDTO.getMinPrice() != 0) {
rangeQuery.gte(searchDTO.getMinPrice());
}
if (searchDTO.getMaxPrice() != 0) {
rangeQuery.lte(searchDTO.getMaxPrice());
}
boolQuery.must(rangeQuery);
}
// 添加关键词查询(如果需要)
if (searchDTO.getKeyWord() != null && !searchDTO.getKeyWord().isEmpty()) {
boolQuery.should(QueryBuilders.matchQuery("courseName", searchDTO.getKeyWord()));
boolQuery.should(QueryBuilders.matchQuery("brief", searchDTO.getKeyWord()));
boolQuery.should(QueryBuilders.matchQuery("teacherName", searchDTO.getKeyWord()));
boolQuery.minimumShouldMatch(1);
}
// 设置查询
queryBuilder.withQuery(boolQuery);
// 增加排序条件,按相关性得分降序排序
queryBuilder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC));
// 构建搜索查询
NativeSearchQuery searchQuery = queryBuilder.build();
// 执行查询
List<CourseDTO> courseList = elasticsearchTemplate.queryForList(searchQuery, CourseDTO.class);
// 设置高亮
if (searchDTO.getKeyWord() != null && !searchDTO.getKeyWord().isEmpty()){
ElasticsearchUtil.highlightKeywords(courseList,searchDTO.getKeyWord());
}
// 进行内存分页
int start = searchDTO.getPageNum() * searchDTO.getPageSize();
int end = Math.min((start + searchDTO.getPageSize()), courseList.size());
Pageable pageable = PageRequest.of(searchDTO.getPageNum(), searchDTO.getPageSize());
if (start > courseList.size()) {
return new PageImpl<>(courseList, pageable, courseList.size());
}
List<CourseDTO> pageCourseList = courseList.subList(start, end);
return new PageImpl<>(pageCourseList, pageable, courseList.size());
}
searchDTO和前端传来的参数一致
public class SearchDTO {
private int minPrice;
private int maxPrice;
private String keyWord;
private int pageNum;
private int pageSize;
}
补充:
我的是根据关键词搜索和价格区间搜索,当值赋值后,高亮会出现html的文本
所以需要使用v-html进行渲染
更多推荐
所有评论(0)