springboot3整合ElasticsearchRepository
分类: springboot 专栏: 新版在线教育项目 标签: elasticSearch ElasticsearchRepository 高亮显示 全文检索
2024-06-11 18:54:45 623浏览
springboot3整合elaticsearch-采用ElasticsearchRepository封装-高亮显示-关键词全文检索等
最终效果
复杂条件查询并分页展示
关键词查询高亮显示
Kibana的简单使用
可能版本不一样的话操作有点出入(下面的截图是用的es8.13.4)
中文分词器的使用
安装了ik分词器,
可以用命令的方式安装,在es安装的bin目录下运行,当然也可以去手动下载分词压缩包后解压到plugins文件夹下(注意建个文件夹analysis-ik或者你对应的分词器)
elasticsearch-plugin.bat install analysis-ik
整合ElasticsearchRepository
es建索引
PUT /course
{
"mappings": {"properties": {
"id":{
"type": "keyword"
},
"cover":{
"type": "keyword",
"index": false
},
"title":{
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"price":{
"type": "double"
},
"subjectParentId":{
"type": "keyword"
},
"subjectParentName":{
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"eduCreate":{
"type": "date"
},
"buyCount":{
"type": "long"
},
"viewCount":{
"type": "long"
},
"description":{
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
}
}}
}
依赖
<!--Elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
spring:
data:
elasticsearch:
repositories:
enabled: true
hostname: localhost
port: 9200
实体类
@Document(indexName = "course")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CourseEntity implements Serializable {
@Id
private String id;
private String cover;//课程封面
@Field(type = FieldType.Text, analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
private String title;//课程标题
private BigDecimal price;//课程价格
private String subjectParentId; //课程一级分类id
@Field(type = FieldType.Text, analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
private String subjectParentName; //课程一级分类名称
private String subjectId;//课程二级分类id
@Field(type = FieldType.Text, analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
private String subjectName;//课程二级分类名称
@Field(type = FieldType.Date)
private Date eduCreate;//添加时间
private Long buyCount;//销量
private Long viewCount;//课程浏览量(不是视频播放量)
@Field(type = FieldType.Text, analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
private String description;//课程介绍
}
dsl语句
get /course/_search
{
"query":{
"multi_match": {
"query":"我想学java",
"fields":
[
"title","subjectName","subjectParentName","description"
]
}
},
"highlight": {
"fields": {
"title": {},
"subjectName":{},
"subjectParentName":{},
"description":{}
},
"pre_tags": "<font color='red'>",
"post_tags": "</font>"
}
}
dao层
@Repository
public interface CourseEntityRepository extends ElasticsearchRepository<CourseEntity, String> {
@Query("{\n" +
" \"multi_match\": {\n" +
" \"query\":\"?0\",\n" +
" \"fields\":\n" +
" [\n" +
" \"title\",\"subjectName\",\"subjectParentName\",\"description\"\n" +
" ]\n" +
" }\n" +
" }")
@Highlight(
fields = {
@HighlightField(name = "title"),
@HighlightField(name = "subjectName"),
@HighlightField(name = "subjectParentName"),
@HighlightField(name = "description")
},
parameters=@HighlightParameters(preTags = "<font color='red'>", postTags = "</font>")
)
//在这个例子中,searchByHit方法使用multi_match查询搜索标题、简介和分类字段。
//?0是一个占位符,它会被方法的参数keyword替换。
List<SearchHit<CourseEntity>> searchByHit(String keyword);
//根据二级分类id查找并分页展示
Page<CourseEntity> findBySubjectId (String subjectId,Pageable pageable);
//根据一级分类id查找并分页展示
Page<CourseEntity> findBySubjectParentId(String subjectParentId,Pageable pageable);
}
返回的page这个不是mybatisPlus的page,而是org.springframework.data.domain.Page
- content:返回当前页的元素列表。
- number:返回当前页的页码,从0开始计数。(切记一定要+1之后才是真正的第几页)
- size:返回每页的大小。
- totalElements:返回总分页元素的数量。
- totalPages:返回总页数。
- last:是否是最后一页
- first:是否是第一页
- hasNext:是否有下一页
- hasPrevious:是否有上一页
service层
前台主要是关键词查和分类排序查
@Service
public class CourseEntityService {
@Autowired
private CourseEntityRepository courseEntityRepository;
//为了高亮显示重新封装了page
public Page<CourseEntity> searchByKeyword(String keyword, Integer number, Integer size) {
if (!StringUtils.hasText(keyword.trim())) {
throw new RuntimeException("必须输入关键词");
}
//先把高亮显示的处理掉
List<SearchHit<CourseEntity>> searchHits = courseEntityRepository.searchByHit(keyword);
List<CourseEntity> newCourseList = new ArrayList<>();
for (SearchHit<CourseEntity> searchHit : searchHits) {
CourseEntity content = searchHit.getContent();
Map<String, List<String>> highlightMap = searchHit.getHighlightFields();
if (highlightMap != null) {
for (Map.Entry<String, List<String>> entry : highlightMap.entrySet()) {
String originalField = entry.getKey();
List<String> highlightContent = entry.getValue();
if (highlightContent != null && !highlightContent.isEmpty()) {
if (originalField.equals("title")) {
content.setTitle(highlightContent.get(0));
} else if (originalField.equals("description")) {
content.setDescription(highlightContent.get(0));
} else if (originalField.equals("subjectName")) {
content.setSubjectName(highlightContent.get(0));
} else if (originalField.equals("subjectParentName")) {
content.setSubjectParentName(highlightContent.get(0));
}
}
}
}
newCourseList.add(content);
}
Pageable pageable = PageRequest.of(number-1, size);
// 计算总记录数
int totalElements = searchHits.size();
// 创建一个新的PageImpl对象
Page<CourseEntity> page = new PageImpl<>(
// 将SearchHit中的CourseEntity对象提取出来,并放入一个新的列表中
newCourseList.stream()
.skip(pageable.getPageNumber() * pageable.getPageSize()) // 跳过前n条记录
.limit(pageable.getPageSize()) // 限制结果集大小
.collect(Collectors.toList()),
pageable, // 分页参数
totalElements // 总记录数
);
// 返回新的Page对象
return page;
}
public Page<CourseEntity> searchBySubject(SearchCourseDto dto, Integer number, Integer size) {
//传了二级分类
if(StringUtils.hasText(dto.getSubjectId().trim())){
//传了排序
if (StringUtils.hasText(dto.getSortField().trim())) {
if(dto.getSortType().equals("des")){
return courseEntityRepository.findBySubjectId(dto.getSubjectId(),PageRequest.of(number-1, size,Sort.by(dto.getSortField()).descending()));
}else{
return courseEntityRepository.findBySubjectId(dto.getSubjectId(),PageRequest.of(number-1, size,Sort.by(dto.getSortField()).ascending()));
}
}else{
//没传排序
return courseEntityRepository.findBySubjectId(dto.getSubjectId(), PageRequest.of(number-1, size));
}
}
//传了一级分类
if(StringUtils.hasText(dto.getSubjectParentId().trim())){
//传了排序
if (StringUtils.hasText(dto.getSortField().trim())) {
if(dto.getSortType().equals("des")){
return courseEntityRepository.findBySubjectParentId(dto.getSubjectParentId(),PageRequest.of(number-1, size,Sort.by(dto.getSortField()).descending()));
}else{
return courseEntityRepository.findBySubjectParentId(dto.getSubjectParentId(),PageRequest.of(number-1, size,Sort.by(dto.getSortField()).ascending()));
}
}else{
//没传排序
return courseEntityRepository.findBySubjectParentId(dto.getSubjectParentId(), PageRequest.of(number-1, size));
}
}
//只传排序
if (StringUtils.hasText(dto.getSortField().trim())) {
if(dto.getSortType().equals("des")){
return courseEntityRepository.findAll(PageRequest.of(number-1, size,Sort.by(dto.getSortField()).descending()));
}else{
return courseEntityRepository.findAll(PageRequest.of(number-1, size,Sort.by(dto.getSortField()).ascending()));
}
}
//什么都不传的情况下查所有
return courseEntityRepository.findAll(PageRequest.of(number-1, size));
}
}
后台增删改es
@Autowired
CourseEntityRepository courseEntityRepository;;
public void addCourse(CourseEntity entity){
courseEntityRepository.save(entity);
}
public void delCourse(String id){
courseEntityRepository.deleteById(id);
}
controller层
后台的
@Operation(summary = "删除课程")
@DeleteMapping("{id}")
public ResultVo del(@PathVariable String id){
eduCourseService.del(id);
//把es里的也删掉
courseEntityService.delCourse(id);
@Operation(summary = "确认发布")
@PostMapping("/status/{cId}")
public ResultVo status(@PathVariable String cId){
EduCourse course = eduCourseService.getById(cId);
if(!course.getStatus().equals("Normal")){//首次发布
//……
//新增一下es
CourseEntity courseEntity= new CourseEntity();
BeanUtils.copyProperties(course,courseEntity);
courseEntity.setDescription(courseDescriptionService.getById(course.getId()).getDescription());
courseEntity.setSubjectName(subjectService.getById(course.getSubjectId()).getTitle());
courseEntity.setSubjectParentName(subjectService.getById(course.getSubjectParentId()).getTitle());
courseEntityService.addCourse(courseEntity);
}
course.setStatus("Normal");
eduCourseService.updateById(course);
return ResultVo.success("",null);
}
@Operation(summary = "添加/修改课程基本信息")
@PostMapping("/saveOrupdate")
public ResultVo saveCourse(@RequestBody CourseInfoVo courseInfoVo){
//1 向课程表添加课程基本信息
//CourseInfoVo对象转换eduCourse对象
EduCourse eduCourse = new EduCourse();
BeanUtils.copyProperties(courseInfoVo,eduCourse);
boolean flag = eduCourseService.saveOrUpdate(eduCourse);
if(flag == false) {
//添加失败
throw new JfException(20001,"添加课程信息失败");
}
//获取添加之后课程id
String cid = eduCourse.getId();
//2 向课程简介表添加课程简介
//edu_course_description
EduCourseDescription courseDescription = new EduCourseDescription();
courseDescription.setDescription(courseInfoVo.getDescription());
//设置描述id就是课程id
courseDescription.setId(cid);
courseDescriptionService.saveOrUpdate(courseDescription);
if(StringUtils.checkValNotNull(courseInfoVo.getId())){
//……
//发布了的课程修改基本信息的时候更新一下es
CourseEntity courseEntity= new CourseEntity();
EduCourse byId = eduCourseService.getById(eduCourse.getId());
BeanUtils.copyProperties(byId,courseEntity);
courseEntity.setDescription(courseDescriptionService.getById(eduCourse.getId()).getDescription());
courseEntity.setSubjectName(subjectService.getById(courseInfoVo.getSubjectId()).getTitle());
courseEntity.setSubjectParentName(subjectService.getById(courseInfoVo.getSubjectParentId()).getTitle());
courseEntityService.addCourse(courseEntity);
}
return ResultVo.success("添加成功",cid);
}
前台的
//根据关键词全文检索-高亮显示
@GetMapping("/search")
@Operation(summary = "根据关键词全文检索-高亮显示")
public ResultVo searchCourses(String keyword,
@RequestParam(defaultValue = "1") Integer number,
@RequestParam(defaultValue = "2")Integer size) {
return ResultVo.success(courseEntityService.searchByKeyword(keyword,number,size));
}
@PostMapping("/search/subject")
@Operation(summary = "分类查询课程")
public ResultVo searchBySubject(@RequestBody
SearchCourseDto dto,
@RequestParam(defaultValue = "1") Integer number,
@RequestParam(defaultValue = "2")Integer size) {
return ResultVo.success(courseEntityService.searchBySubject(dto,number,size));
}
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
暂无评论,快来写一下吧
展开评论
他的专栏
他感兴趣的技术