文章目录
- 🌞 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 是我个人开源的一款基于 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.新增几条记录
2.查询
3.结果高亮显示
3.加上控制层的实现
1.DTO和BO都加上keyWord属性
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;
}