当前位置: 首页 > news >正文

实现高亮的全文分页检索

文章目录

  • 🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)
    • 🌟 亮点功能
    • 📦 spring cloud模块概览
      • 常用工具
    • 🔗 更多信息
    • 1.sun-club-infra 模块
        • SubjectEsServiceImpl.java
          • 1.querySubjectList方法:根据查询请求进行查询
          • 2.convertHit2SubjectInfoEs方法:将每一个hit转换为SubjectInfoEs
          • 3.根据信息构建一个查询请求对象
    • 2.简单测试
        • 1.TestFeignController.java
        • 2.新增几条记录
        • 2.查询
        • 3.结果高亮显示
    • 3.加上控制层的实现
        • 1.DTO和BO都加上keyWord属性
        • 2.SubjectController.java
        • 3.sun-club-domain
          • 1.SubjectInfoDomainService.java
          • 2.SubjectInfoDomainServiceImpl.java
        • 4.测试
          • 1.es报错,requires query value
          • 2.发现转换器没有将keyWord转换,所以clean-package一下maven即可
          • 3.重新测试

🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)

Sun Frame Banner

轻松高效的现代化开发体验

Sun Frame 是我个人开源的一款基于 SpringBoot 的轻量级框架,专为中小型企业设计。它提供了一种快速、简单且易于扩展的开发方式。

我们的开发文档记录了整个项目从0到1的任何细节,实属不易,请给我们一个Star!🌟
您的支持是我们持续改进的动力。

🌟 亮点功能

  • 组件化开发:灵活选择,简化流程。
  • 高性能:通过异步日志和 Redis 缓存提升性能。
  • 易扩展:支持多种数据库和消息队列。

📦 spring cloud模块概览

  • Nacos 服务:高效的服务注册与发现。
  • Feign 远程调用:简化服务间通信。
  • 强大网关:路由与限流。

常用工具

  • 日志管理:异步处理与链路追踪。
  • Redis 集成:支持分布式锁与缓存。
  • Swagger 文档:便捷的 API 入口。
  • 测试支持:SpringBoot-Test 集成。
  • EasyCode:自定义EasyCode模板引擎,一键生成CRUD。

🔗 更多信息

  • 开源地址:Gitee Sun Frame
  • 详细文档:语雀文档
    在这里插入图片描述

1.sun-club-infra 模块

SubjectEsServiceImpl.java
1.querySubjectList方法:根据查询请求进行查询
@Override
public PageResult<SubjectInfoEs> querySubjectList(SubjectInfoEs req) {// 构建一个返回的分页对象PageResult<SubjectInfoEs> pageResult = new PageResult<>();// 根据信息构建一个查询请求对象EsSearchRequest esSearchRequest = createSearchListQuery(req);// 获得分页查询结果SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);// 构建一个要返回的数据对象List<SubjectInfoEs> subjectInfoEsList = new LinkedList<>();// 得到命中的数据SearchHits searchHits = searchResponse.getHits();if (searchHits == null || searchHits.getHits() == null) {pageResult.setPageNo(req.getPageNo());pageResult.setPageSize(req.getPageSize());pageResult.setRecords(subjectInfoEsList);pageResult.setTotal(0);return pageResult;}// 如果有命中的SearchHit[] hits = searchHits.getHits();for (SearchHit hit : hits) {// 将每个hit都转换为SubjectInfoEs,然后将其放到要返回的数据对象中SubjectInfoEs subjectInfoEs = convertHit2SubjectInfoEs(hit);subjectInfoEsList.add(subjectInfoEs);}// 构建分页对象pageResult.setPageNo(req.getPageNo());pageResult.setPageSize(req.getPageSize());pageResult.setRecords(subjectInfoEsList);pageResult.setTotal(Long.valueOf(searchHits.getTotalHits().value).intValue());return pageResult;
}
2.convertHit2SubjectInfoEs方法:将每一个hit转换为SubjectInfoEs
/*** 将每一个hit转换为SubjectInfoEs* @param hit* @return*/
private SubjectInfoEs convertHit2SubjectInfoEs(SearchHit hit) {Map<String, Object> sourceAsMap = hit.getSourceAsMap();if (CollectionUtils.isEmpty(sourceAsMap)) {return null;}SubjectInfoEs result = new SubjectInfoEs();// 封装基本数据result.setSubjectId(MapUtils.getLong(sourceAsMap, EsSubjectFields.SUBJECT_ID));result.setSubjectName(MapUtils.getString(sourceAsMap, EsSubjectFields.SUBJECT_NAME));result.setSubjectAnswer(MapUtils.getString(sourceAsMap, EsSubjectFields.SUBJECT_ANSWER));result.setDocId(MapUtils.getLong(sourceAsMap, EsSubjectFields.DOC_ID));result.setSubjectType(MapUtils.getInteger(sourceAsMap, EsSubjectFields.SUBJECT_TYPE));result.setScore(new BigDecimal(String.valueOf(hit.getScore())).multiply(new BigDecimal("100.00").setScale(2, RoundingMode.HALF_UP)));//处理name的高亮Map<String, HighlightField> highlightFields = hit.getHighlightFields();HighlightField subjectNameField = highlightFields.get(EsSubjectFields.SUBJECT_NAME);if(Objects.nonNull(subjectNameField)){Text[] fragments = subjectNameField.getFragments();StringBuilder subjectNameBuilder = new StringBuilder();for (Text fragment : fragments) {subjectNameBuilder.append(fragment);}result.setSubjectName(subjectNameBuilder.toString());}//处理答案高亮HighlightField subjectAnswerField = highlightFields.get(EsSubjectFields.SUBJECT_ANSWER);if(Objects.nonNull(subjectAnswerField)){Text[] fragments = subjectAnswerField.getFragments();StringBuilder subjectAnswerBuilder = new StringBuilder();for (Text fragment : fragments) {subjectAnswerBuilder.append(fragment);}result.setSubjectAnswer(subjectAnswerBuilder.toString());}return result;
}
3.根据信息构建一个查询请求对象
    /*** 根据信息构建一个查询请求对象* @param req* @return*/private EsSearchRequest createSearchListQuery(SubjectInfoEs req) {EsSearchRequest esSearchRequest = new EsSearchRequest();// bq用来组合查询条件BoolQueryBuilder bq = new BoolQueryBuilder();// 查询条件1是根据题目名称查询MatchQueryBuilder subjectNameQueryBuilder =QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_NAME, req.getKeyWord());// 查询条件2是根据题目的答案查询MatchQueryBuilder subjectAnswerQueryBuilder =QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_ANSWER, req.getKeyWord());// 使用bq关联两个查询条件,should就相当于或者,就是两个都查bq.should(subjectNameQueryBuilder);// 让题目名的权重高2subjectNameQueryBuilder.boost(2);bq.should(subjectAnswerQueryBuilder);// 查询条件3是只查询简答题MatchQueryBuilder subjectTypeQueryBuilder =QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_TYPE, SubjectInfoTypeEnum.BRIEF.getCode());// 必须是简答题bq.must(subjectTypeQueryBuilder);// 至少命中一个shouldbq.minimumShouldMatch(1);// 增加高亮HighlightBuilder highlightBuilder = new HighlightBuilder().field("*").requireFieldMatch(false);highlightBuilder.preTags("<span style = \"color:red\">");highlightBuilder.postTags("</span>");// 组装请求// bqesSearchRequest.setBq(bq);// 高亮esSearchRequest.setHighlightBuilder(highlightBuilder);// 匹配字段(一般是全部)esSearchRequest.setFields(EsSubjectFields.FIELD_QUERY);// ==========返回分页查询的结果==========// 当前页是从第几条记录开始,下标从1开始esSearchRequest.setFrom((req.getPageNo() - 1) * req.getPageSize());// 页面大小esSearchRequest.setSize(req.getPageSize());// ==========返回分页查询的结果==========// 不需要快照缓存esSearchRequest.setNeedScroll(false);return esSearchRequest;}

2.简单测试

1.TestFeignController.java
    @RequestMapping("/querySubjectByKeyword")public void querySubjectByKeyword() {SubjectInfoEs subjectInfoEs = new SubjectInfoEs();subjectInfoEs.setKeyWord("简答题目");PageResult<SubjectInfoEs> subjectInfoEsPageResult = subjectEsService.querySubjectList(subjectInfoEs);// 打印log.info("querySubjectByKeyword:" + JSON.toJSONString(subjectInfoEsPageResult));}
}
2.新增几条记录

image-20240621131902122

2.查询

image-20240621131919068

3.结果高亮显示

image-20240621131958040

3.加上控制层的实现

1.DTO和BO都加上keyWord属性

image-20240621134333208

image-20240621134345542

2.SubjectController.java
/*** 全文检索* @param subjectInfoDTO* @return*/
@PostMapping("/getSubjectPageBySearch")
public Result<SubjectInfoEs> getSubjectPageBySearch(@RequestBody SubjectInfoDTO subjectInfoDTO) {try {// 打印日志if (log.isInfoEnabled()) {log.info("SubjectController getSubjectPageBySearch SubjectInfoDTO, subjectInfoDTO:{}", JSON.toJSONString(subjectInfoDTO));}// 参数校验Preconditions.checkArgument(StringUtils.isNotBlank(subjectInfoDTO.getKeyWord()), "关键字不能为空");// DTO转BOSubjectInfoBO subjectInfoBO = SubjectInfoDTOConverter.INSTANCE.convertDTO2BO(subjectInfoDTO);// 设置分页参数subjectInfoBO.setPageNo(subjectInfoDTO.getPageNo());subjectInfoBO.setPageSize(subjectInfoDTO.getPageSize());// 全文检索PageResult<SubjectInfoEs> boPageResult = subjectInfoDomainService.getSubjectPageBySearch(subjectInfoBO);return Result.ok(boPageResult);} catch (Exception e) {log.error("SubjectController getSubjectPageBySearch error, subjectInfoDTO:{}", e.getMessage(), e);return Result.fail("全文检索失败");}
}
3.sun-club-domain
1.SubjectInfoDomainService.java
/*** 全文检索* @param subjectInfoBO* @return*/
PageResult<SubjectInfoEs> getSubjectPageBySearch(SubjectInfoBO subjectInfoBO);
2.SubjectInfoDomainServiceImpl.java
@Override
public PageResult<SubjectInfoEs> getSubjectPageBySearch(SubjectInfoBO subjectInfoBO) {// 将bo转换为entitySubjectInfoEs subjectInfoEs = new SubjectInfoEs();subjectInfoEs.setKeyWord(subjectInfoBO.getKeyWord());subjectInfoEs.setPageNo(subjectInfoBO.getPageNo());subjectInfoEs.setPageSize(subjectInfoBO.getPageSize());// 全文检索PageResult<SubjectInfoEs> subjectInfoEsPageResult = subjectEsService.querySubjectList(subjectInfoEs);return subjectInfoEsPageResult;
}
4.测试
1.es报错,requires query value

image-20240621134034359

2.发现转换器没有将keyWord转换,所以clean-package一下maven即可

image-20240621134110243

image-20240621134223762

3.重新测试

image-20240621134708128

http://www.lryc.cn/news/423128.html

相关文章:

  • 【buildroot与yocto区别】
  • 原创音乐小程序的设计
  • 使用 MongoDB 构建 AI:Flagler Health 的 AI 旅程如何彻底改变患者护理
  • 在 Linux 系统中下载 Python 并配置环境
  • 优化if-else的几种方式
  • 关于k8s集群Pod启动过程
  • Linux Vim教程(十五):使用Vimscript进行脚本编写
  • 解决element-ui回车键绑定按钮功能后却刷新浏览器的问题
  • MySQL基础练习题37-查找结果的质量和占比
  • 酒店行业如何利用XML进行营销短信
  • 【模型】TFLiteModel
  • 【Kubernetes】Service 概念与实战
  • RTSP|RTMP流如何指定坐标位置和分辨率获取RGB数据实时渲染和算法分析
  • 基于ssm+vue+uniapp的英语学习交流平台小程序
  • 如何判断一个TimerTask是否已经完成
  • Android常用面试题
  • JSON与Jsoncpp库:数据交换的灵活选择
  • salesforce rich text 字段支持html中内嵌JavaScript吗
  • Ubuntu24.04、22.04或20.04安装Golang方法教程
  • 学习记录第二十二天
  • 红酒与艺术展览:品味艺术与风味的双重盛宴
  • 1Panel配置
  • 场外期权是如何定价的?场外期权定价的基本原理是什么?
  • vue中数据持久化
  • 小白零基础学数学建模系列-Day3-线性回归模型的构建与评估
  • Flutter中的 extended_nested_scroll_view 库:介绍与使用指南
  • Elasticsearch 综合搜索案例解析
  • Web存储革命:揭秘JavaScript的会话存储(sessionStorage)
  • 基于python的百度迁徙迁入、迁出数据分析(九)
  • 2025上海礼品展 华东礼品工艺品展览会