当前位置: 首页 > 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

相关文章:

实现高亮的全文分页检索

文章目录 &#x1f31e; Sun Frame&#xff1a;SpringBoot 的轻量级开发框架&#xff08;个人开源项目推荐&#xff09;&#x1f31f; 亮点功能&#x1f4e6; spring cloud模块概览常用工具 &#x1f517; 更多信息1.sun-club-infra 模块SubjectEsServiceImpl.java1.querySubje…...

【buildroot与yocto区别】

buildroot与yocto区别 Buildroot和Yocto的主要区别在于它们的使用目的、构建过程、以及输出的内容。 使用目的&#xff1a;Buildroot主要用于构建根文件系统&#xff0c;而Yocto项目则用于帮助开发人员为嵌入式产品创建定制的基于‌Linux的系统。Yocto项目不仅仅构建根文件系…...

原创音乐小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;歌曲类型管理&#xff0c;歌曲信息管理&#xff0c;热门歌手管理&#xff0c;音乐资讯管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;歌曲信息&a…...

使用 MongoDB 构建 AI:Flagler Health 的 AI 旅程如何彻底改变患者护理

Flagler Health 致力于为慢性病患者提供支持&#xff0c;为其匹配合适的医生以提供合适的护理。 通常&#xff0c;身患严重病痛的患者面临的选择有限&#xff0c;他们往往需要长期服用阿片类药物&#xff0c;或寻求成本高昂的侵入性外科手术干预。遗憾的是&#xff0c;后一种方…...

在 Linux 系统中下载 Python 并配置环境

哈喽&#xff0c;大家好&#xff0c;木易巷来啦&#xff01; 在 Linux 系统中下载 Python 并配置环境&#xff0c;主要包含以下几个核心步骤&#xff1a; ▍1、安装 Python 多数 Linux 发行版已预装 Python&#xff0c;但您可能需要安装不同版本或更新现有版本。 打开终端。 …...

优化if-else的几种方式

优化if-else的几种方式 策略模式1、创建支付策略接口2、书写不同的支付方式逻辑代码微信支付QQ支付 3、service层的实现类使用4、controller层的调用说明 枚举与策略模式结合1、创建枚举2、service层书写处理方法3、controller层调用4、说明 Lambda表达式与函数接口说明 策略模…...

关于k8s集群Pod启动过程

目录 1.Pod启动阶段&#xff08;相位 phase&#xff09; 1.1 phase的可能状态 2.Pod故障排除步骤 3.总结 1.Pod启动阶段&#xff08;相位 phase&#xff09; Pod 创建完之后&#xff0c;一直到持久运行起来&#xff0c;中间有很多步骤&#xff0c;也就有很多出错的可能&…...

Linux Vim教程(十五):使用Vimscript进行脚本编写

目录 1. Vimscript简介 2. 基本语法和结构 2.1 变量 2.2 条件语句 2.3 循环语句 2.4 函数 3. 操作缓冲区、窗口和标签页 3.1 缓冲区 3.2 窗口 3.3 标签页 4. 自动化编辑任务 4.1 自动命令 4.2 键映射 5. 编写和调试Vimscript脚本 5.1 编写脚本 5.2 调试脚本 6…...

解决element-ui回车键绑定按钮功能后却刷新浏览器的问题

最近写代码时&#xff0c;遇到要给回车键绑定确定的功能&#xff0c;并且打开对话框时要自动获取输入框焦点&#xff0c;发现一但重新打开浏览器&#xff0c;第一次执行回车键的功能时就会刷新浏览器&#xff0c;后续则会成功执行。但是一但再一次重新打开浏览器&#xff0c;还…...

MySQL基础练习题37-查找结果的质量和占比

目录 题目 准备数据 分析数据 总结 题目 找出每次的 query_name 、 quality 和 poor_query_percentage。 quality 和 poor_query_percentage 都应 四舍五入到小数点后两位 。 准备数据 ## 创建库 create database db; use db;## 创建表 Create table If Not Exists Que…...

酒店行业如何利用XML进行营销短信

随着信息社会的到来&#xff0c;消费者获得会所的服务也从单纯的电话方式&#xff0c;逐渐转变为电话、互联网、传真&#xff0c;群发短信等多种媒体并行的方式。今天着重介绍下酒店行业如何利用短信平台进行营销。 群发短信业务对酒店起到的效率&#xff1a;根据新产品或服务向…...

【模型】TFLiteModel

TFLiteModel 指的是 TensorFlow Lite&#xff08;TFLite&#xff09;模型&#xff0c;它是 TensorFlow 的轻量级解决方案&#xff0c;用于在移动设备、嵌入式系统和物联网设备上运行机器学习模型。TFLite 模型通常是从 TensorFlow 模型转换而来的&#xff0c;并且经过了优化&am…...

【Kubernetes】Service 概念与实战

Service 概念与实战 1.通过 Service 向外部暴露 Pod2.Service 的多端口设置3.集群内部的 DNS 服务4.无头 Service 在 Kubernetes 中部署的应用可能对应一个或者多个 Pod&#xff0c;而每个 Pod 又具有独立的 IP 地址。Service&#xff08;服务&#xff09;能够为一组功能相同的…...

RTSP|RTMP流如何指定坐标位置和分辨率获取RGB数据实时渲染和算法分析

接上一篇blog&#xff1a;同一路RTSP|RTMP流如何同时回调YUV和RGB数据实现渲染和算法分析-CSDN博客 我们知道&#xff0c;由于解码后的YUV或RGB数据size比较大&#xff0c;如果想把转换后的RGB数据传给比如python算法的话&#xff0c;数据量还是挺大&#xff0c;为此&#xff…...

基于ssm+vue+uniapp的英语学习交流平台小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…...

如何判断一个TimerTask是否已经完成

如何判断一个TimerTask是否已经完成 判断TimerTask是否已经完成并不是TimerTask或Timer类直接提供的功能&#xff0c;因为TimerTask一旦被提交给Timer执行&#xff0c;它就在一个独立的线程中运行&#xff0c;而Timer类并不直接提供方法来查询或控制任务的执行状态。 然而&am…...

Android常用面试题

1、如何理解Java的多态&#xff1f;其中&#xff0c;重载和重写有什么区别&#xff1f; 2、谈一下JVM内存区域划分&#xff1f;哪部分是线程公有的&#xff0c;哪部分是私有的&#xff1f; 3、final关键字的用法&#xff1f; 4、死锁是怎么导致的&#xff1f;如何定位死锁 5、数…...

JSON与Jsoncpp库:数据交换的灵活选择

目录 引言 一.JSON简介 二. Jsoncpp库概述 三. Jsoncpp核心类介绍 3.1 Json::Value类 3.2 序列化与反序列化类 四. 实现序列化 五. 实现反序列化 结语 引言 在现代软件开发中&#xff0c;数据交换格式扮演着至关重要的角色。JSON&#xff08;JavaScript Object Notati…...

salesforce rich text 字段支持html中内嵌JavaScript吗

Salesforce 的富文本字段&#xff08;Rich Text Field&#xff09;不支持在 HTML 中内嵌 JavaScript。为了安全&#xff0c;Salesforce 会自动移除或过滤用户输入中的任何 JavaScript 代码。这是为了防止跨站点脚本&#xff08;XSS&#xff09;攻击&#xff0c;从而保护 Salesf…...

Ubuntu24.04、22.04或20.04安装Golang方法教程

在Ubuntu Linux&#xff08;例如 Ubuntu 24.04、22.04 或 20.04&#xff09;上安装Go&#xff08;Golang&#xff09;是一个简单的过程。我们可以使用默认系统存储库使用本教程中给出的命令下载开源 Go 编程语言&#xff0c;轻松构建简单、可靠和高效的软件。 Go语言由Google…...

Amazon Q 从入门到实战,AWS 专属 AI 助手超全指南

目录 一、Amazon Q 到底是什么 二、Amazon Q 有两个版本 1、Amazon Q Developer&#xff08;给开发者/运维&#xff09; 2、Amazon Q Bussiness&#xff08;给企业/业务人员&#xff09; 三、Amazon Q能解决什么实际问题 四、Amazon Q 和 Chat GPT 同类助手的有什么区别 …...

AI核心概念解析:Agent、Prompt、Skill 及生态关系

&#x1f310; AI核心概念解析&#xff1a;Agent、Prompt、Skill 及生态关系 一、关键名词正确定义与原理 1. Agent&#xff08;智能体&#xff09; 指具备感知—决策—行动闭环能力的自主软件实体。它不是单个模型&#xff0c;而是一个系统架构&#xff1a;接收输入&#x…...

OpenClaw压力测试:Qwen3-14B在并发请求下的响应延迟分析

OpenClaw压力测试&#xff1a;Qwen3-14B在并发请求下的响应延迟分析 1. 测试背景与目标 上周在部署OpenClaw对接本地Qwen3-14B模型时&#xff0c;遇到一个实际问题&#xff1a;当我同时触发多个自动化任务时&#xff0c;系统响应明显变慢&#xff0c;甚至偶尔会出现任务失败。…...

探索NextDNS Config:优化你的DNS配置以提升网络性能

探索NextDNS Config&#xff1a;优化你的DNS配置以提升网络性能 是一个开源项目&#xff0c;旨在帮助用户轻松地管理并优化其设备上的NextDNS设置。该项目由Yokoffing开发&#xff0c;并提供了多种平台&#xff08;包括路由器、Android和iOS&#xff09;的配置文件&#xff0c;…...

解析器开发的终极革命:为什么Ohm比传统解析器更强大?

解析器开发的终极革命&#xff1a;为什么Ohm比传统解析器更强大&#xff1f; 【免费下载链接】ohm A library and language for building parsers, interpreters, compilers, etc. 项目地址: https://gitcode.com/gh_mirrors/oh/ohm Ohm是一个用于构建解析器、解释器和编…...

终极指南:gin-vue-admin前端错误监控告警配置详解 - 邮件与钉钉实时通知方案

终极指南&#xff1a;gin-vue-admin前端错误监控告警配置详解 - 邮件与钉钉实时通知方案 【免费下载链接】gin-vue-admin &#x1f680;ViteVue3Gin拥有AI辅助的基础开发平台&#xff0c;企业级业务AI开发解决方案&#xff0c;内置mcp辅助服务&#xff0c;内置skills管理&#…...

M5Stamp C3 Mate LED驱动库:基于RMT的WS2812B精简控制方案

1. 项目概述M5StampC3LED 是专为 M5Stamp C3 Mate 模块设计的 LED 控制库&#xff0c;其本质是一个轻量级封装层&#xff0c;用于驱动板载的 Adafruit NeoPixel&#xff08;WS2812B 兼容&#xff09;RGB LED。该库不直接实现底层时序协议&#xff0c;而是基于 ESP-IDF 或 Ardui…...

神马网站 SEO 优化对网站转化率的影响

神马网站 SEO 优化对网站转化率的影响 在当今互联网时代&#xff0c;网站的流量和转化率直接关系到企业的销售和品牌的知名度。仅仅拥有流量并不意味着一切都顺风顺水&#xff0c;如何把这些流量转化为实际的业务和销售&#xff0c;这就涉及到神马网站的SEO优化对网站转化率的…...

5G网络架构:核心网、接入网的组成与工作原理

5G网络架构&#xff1a;核心网、接入网的组成与工作原理&#x1f4dd; 本章学习目标&#xff1a;本章探讨网络编程&#xff0c;帮助读者掌握网络应用开发技能。通过本章学习&#xff0c;你将全面掌握"5G网络架构&#xff1a;核心网、接入网的组成与工作原理"这一核心…...

开发环境配置实战:通过Anaconda Prompt高效管理虚拟环境与Jupyter内核

1. 为什么需要Anaconda Prompt管理虚拟环境 作为数据科学领域的开发者&#xff0c;我经历过无数次Python环境混乱带来的痛苦。记得有一次在交付项目前&#xff0c;突然发现本地运行的模型在服务器上完全无法复现&#xff0c;排查了半天才发现是numpy版本不兼容的问题。这种经历…...