springboot3整合ElasticsearchRepository

飞一样的编程
飞一样的编程
擅长邻域:Java,MySQL,Linux,nginx,springboot,mongodb,微信小程序,vue

分类: springboot 专栏: 新版在线教育项目 标签: elasticSearch ElasticsearchRepository 高亮显示 全文检索

2024-06-11 18:54:45 112浏览

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

  1. content:返回当前页的元素列表。
  2. number:返回当前页的页码,从0开始计数。(切记一定要+1之后才是真正的第几页)
  3. size:返回每页的大小。
  4. totalElements:返回总分页元素的数量。
  5. totalPages:返回总页数。
  6. last:是否是最后一页
  7. first:是否是第一页
  8. hasNext:是否有下一页
  9. 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展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695