校园课程助手【4】-使用Elasticsearch实现课程检索
本节将介绍本项目的查询模块,使用Elasticsearch又不是查询接口,具体流程如图所示(如果不了解Elasticsearch可以使用sql语句进行查询):
这里是两种方法的异同点:
- Mysql:擅长事务类型操作,可以确保数据的安全和一致性
- Elasticsearch:擅长海量数据的搜索、分析、计算
- 对安全性要求较高的写操作,使用mysql实现
- 对查询性能要求较高的搜索需求,使用elasticsearch实现
- 两者再基于某种方式,实现数据的同步,保证一致性
具体流程:
1.导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>
2.在application.yum引入配置
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>
3.在项目中建立elasticsearch.document和elasticsearch.repository包,用于存放elasticsearch文档类和接口操作
package com.java.elasticsearch.document;import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;import java.math.BigDecimal;@Document(indexName = "course")
public class CourseInfo {@Idprivate String courseId;@Field(type = FieldType.Text, analyzer = "standard") // 使用标准分析器private String courseName;@Field(type = FieldType.Text, analyzer = "standard") // 使用标准分析器private String courseTeacher;@Field(type = FieldType.Text)private String courseDetail;@Field(type = FieldType.Integer)private Integer courseAttribute;@Field(type = FieldType.Double)private BigDecimal coursePrice;@Field(type = FieldType.Integer)private Integer courseStock;// 构造函数、getter 和 setter 方法// Getters and setters for each fieldpublic String getCourseId() {return courseId;}public void setCourseId(String courseId) {this.courseId = courseId;}public String getCourseName() {return courseName;}public void setCourseName(String courseName) {this.courseName = courseName;}public String getCourseTeacher() {return courseTeacher;}public void setCourseTeacher(String courseTeacher) {this.courseTeacher = courseTeacher;}public String getCourseDetail() {return courseDetail;}public void setCourseDetail(String courseDetail) {this.courseDetail = courseDetail;}public Integer getCourseAttribute() {return courseAttribute;}public void setCourseAttribute(Integer courseAttribute) {this.courseAttribute = courseAttribute;}public BigDecimal getCoursePrice() {return coursePrice;}public void setCoursePrice(BigDecimal coursePrice) {this.coursePrice = coursePrice;}public Integer getCourseStock() {return courseStock;}public void setCourseStock(Integer courseStock) {this.courseStock = courseStock;}
}
4、在repository包下新建操作Elasticsearch的接口继承ElasticsearchRepository
package com.java.elasticsearch.repository;import com.java.elasticsearch.document.CourseInfo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;public interface CourseRepository extends ElasticsearchRepository<CourseInfo, String> {// 按课程名查询Page<CourseInfo> findByCourseName(String courseName, int courseAttribute, Pageable pageable);// 按授课老师名查询Page<CourseInfo> findByCourseTeacher(String courseTeacher, int courseAttribute,Pageable pageable);// 查询课程名为courseName且授课老师为courseTeacher的记录@Query("{\"bool\": {\"must\": [{\"match\": {\"courseName\": \"?0\"}}, {\"match\": {\"courseTeacher\": \"?1\"}}]}}")Page<CourseInfo> findByCourseNameAndCourseTeacher(String courseName, String courseTeacher, Pageable pageable);
}
5.在service包下新建Elasticsearch课程搜索Service类EsCourseService
package com.java.service;import com.java.elasticsearch.document.EsCourse;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;import java.util.List;public interface EsCourseService {/*** 从数据库中导入课程到ES* @return*/int importAll();/*** 根据id删除课程* @param id*/void delete(Long id);/*** 根据id创建商品* @param id* @return*/EsProduct create(Long id);/*** 批量删除* @param ids*/void deletes(List<Long> ids);/*** 根据关键字搜索* @param keyword* @param pageNum* @param pageSize* @return*/Page<EsProduct> searchPage(String keyword, Integer pageNum,Integer pageSize);
}
实现上述方法
package com.java.service.impl;import com.java.dao.EsProductDao;
import com.java.elasticsearch.document.EsProduct;
import com.java.elasticsearch.repository.EsProductRepository;
import com.java.service.EsProductService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;@Service
@Transactional
public class EsProductServiceImpl implements EsProductService {private static final Logger logger = LoggerFactory.getLogger(EsProductServiceImpl.class);@Autowiredprivate EsProductDao esProductDao;@Autowiredprivate EsProductRepository esProductRepository;@Overridepublic int importAll() {List<EsProduct> esProductList = esProductDao.getProductEs(null);Iterable<EsProduct> iterable = esProductRepository.saveAll(esProductList);Iterator<EsProduct> iterator = iterable.iterator();logger.info("导入ES数据{}:",iterator);int count = 0;while (iterator.hasNext()) {count++;iterator.next();}return count;}@Overridepublic void delete(Long id) {logger.info("删除ES中的商品{}:",id);esProductRepository.deleteById(id);}@Overridepublic EsProduct create(Long id) {List<EsProduct> esProducts = esProductDao.getProductEs(id);if (CollectionUtils.isEmpty(esProducts)) {return null;}EsProduct esProduct = esProducts.get(0);logger.info("导入ES单条商品{}:",esProduct);return esProductRepository.save(esProduct);}@Overridepublic void deletes(List<Long> ids) {if (!CollectionUtils.isEmpty(ids)) {List<EsProduct> esProductList = new ArrayList<>();ids.forEach(id->{EsProduct esProduct = new EsProduct();esProduct.setId(id);esProductList.add(esProduct);});logger.info("批量删除ES中的商品{}:",esProductList);esProductRepository.deleteAll(esProductList);}}@Override// 搜索课程public Page<CourseInfo> searchCourses(String query, Integer courseAttribute, Pageable pageable) {if (query != null && !query.isEmpty()) {return courseRepository.findByCourseNameOrCourseTeacher(query, query, pageable);} else {// 如果没有搜索词,则返回所有符合条件的课程return courseRepository.findByCourseAttributeAndCourseStockGreaterThan(courseAttribute, pageable);}}
}
6.在dao包下新建操作数据库接口EsProductDao和映射xml文件EsProductDao.xml
package com.java.dao;
import java.util.List;public interface EsCourseDao {List<EsProduct> selectAllCourse();
}
<!-- src/main/resources/mapper/EsCourseDao.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java.dao.EsProductDao"><resultMap id="CourseResultMap" type="EsCourse"><result property="course_id" column="course_id"/><result property="course_name" column="course_name"/><result property="course_teacher" column="course_teacher"/><result property="course_attribute" column="course_attribute"/><result property="course_stock" column="course_stock"/></resultMap><!-- 查询所有课程 --><select id="selectAllCourse" resultMap="CourseResultMap">SELECT course_id,course_name,course_teacher,course_attribute ,course_stockFROM course</select></mapper>
7.在controller包下新建控制器EsProductController
/*** ES搜索课程Controller**/
@Controller
@Api(tags = "EsProductController",description = "ES课程搜索")
public class EsProductController {@Autowiredprivate EsProductService esProductService;@ApiOperation("从数据库导入ES课程数据")@RequestMapping(value = "/esProduct/importAll",method = RequestMethod.POST)@ResponseBodypublic CommonResult<Integer> importAll(){int count = esProductService.importAll();return CommonResult.success(count);}@ApiOperation("根据id删除课程")@RequestMapping(value = "/esProduct/delete/{id}",method = RequestMethod.POST)@ResponseBodypublic CommonResult deleteById(@PathVariable Long id){esProductService.delete(id);return RespBean.success("删除成功");}@ApiOperation("批量删除课程")@RequestMapping(value = "/esProduct/deletes",method = RequestMethod.POST)@ResponseBodypublic CommonResult deleteById(List<Long> ids){esProductService.deletes(ids);return RespBean.success("删除成功");}@ApiOperation("根据id创建课程")@RequestMapping(value = "/esProduct/create",method = RequestMethod.POST)@ResponseBodypublic CommonResult create(Long id){EsProduct esProduct = esProductService.create(id);if (StringUtils.isEmpty(esProduct)) {return CommonResult.failed("创建失败");}return RespBean.success("创建成功");}@ApiOperation("搜索课程")@RequestMapping(value = "/esProduct/search",method = RequestMethod.GET)@ResponseBodypublic CommonResult<CommonPage<EsProduct>> search(@RequestParam(required = false) String keyword,@RequestParam(required = false, defaultValue = "0") Integer pageNum,@RequestParam(required = false, defaultValue = "5") Integer pageSize){Page<EsProduct> esProductPage = esProductService.searchPage(keyword,pageNum,pageSize);return RespBean.success(CommonPage.restPage(esProductPage));}
}
相关文章:

校园课程助手【4】-使用Elasticsearch实现课程检索
本节将介绍本项目的查询模块,使用Elasticsearch又不是查询接口,具体流程如图所示(如果不了解Elasticsearch可以使用sql语句进行查询): 这里是两种方法的异同点: Mysql:擅长事务类型操作&#…...
经典运维面试题
1、Linux常见的日志文件都有哪些,各自的用途?日志轮询配置文件在哪里?欢迎界面配置文件在哪里? /var/log/messages #内核及公共消息日志/var/log/cron #计划任务日志/var/log/dmesg #系统引导日志/var/log/malilog #邮件系…...

别再盲目推广了!Xinstall助你开启App线下推广新篇章
在这个数字化飞速发展的时代,App已经成为我们生活中不可或缺的一部分。然而,App市场的竞争也日益激烈,如何让你的App在众多竞争者中脱颖而出,成为每个推广者必须面对的问题。今天,就让我们一起探讨一下App线下推广的痛…...

大厂linux面试题攻略五之数据库管理
一、数据库管理-MySQL语句 0.MySQL基本语句: 1.SQL语句-增 创建xxx用户: mysql>create user xxx % indentified by 123456; xxx表示用户名 %b表示该用户用来连接数据库的方式(远程或本地连接) indentified by 123456设置密码…...
【pytorch】模型集成
在集成学习中,我们会训练多个模型(通常称为「弱学习器」)解决相同的问题,并将它们结合起来以获得更好的结果。最重要的假设是:当弱模型被正确组合时,我们可以得到更精确和/或更鲁棒的模型。 常用的模型集成…...

初识集合和数据结构
目录 初识集合框架数据结构基本概念和术语数据数据元素数据项数据对象前四者的关系数据结构逻辑结构和物理结构逻辑结构物理结构 算法算法设计要求 初识集合框架 Java的集合框架也可被称为容器,是定义在Java.util包下的一些接口和实现类。其就是将多个元素存储到一…...

cocos creator 3.x中动态加载 resources 文件夹下的图片时提示找不到
文件目录如下 类型为spriteFrame 代码案例 图片设置为 sprite-frame、texture 或其他图片类型后,将会在 资源管理器 中生成一个对应类型的资源。但如果直接加载 equipments/testea,得到的类型将会是 ImageAsset,必须指定路径到具体的子资源…...
第九十八周周报
学习时间: 2024.7.27-204.8.3 学习产出: 这周主要在按照审稿人的意见修改论文,由于有个模型保存的文件找不到了,所以重新训练花了点时间,目前已经把修改后的论文和cover letter发给杨老师了。...
程序员找工作之数据结构面试题总结分析
文章目录 1. 数据结构的基本概念与分类2. 数据结构的存储与表示3. 数据元素的存储与关系4. 存储结构的选择与考量5. 特定数据结构的定义与特性6. 数据结构操作与应用7. 数组与存储8. 特定数据结构的存储与访问 程序员在找工作面试中,数据结构方面可能会被问到的问题…...
设置provider解决maven找不到JUnit 5测试样例
问题描述 尝试复现一个用大模型生成测试样例的工作,但使用maven生成的JUnit 5测试样例死活不执行。又不想用命令行运行,因此进行排查 基本知识 <dependencies> junit-jupiter-api JUnit 5写代码时调用的库 junit-jupyter-engine 运行JUnit 5测…...

php反序列化靶机serial实战
扫描ip,找到靶机ip后进入 他说这是cookie的测试网页,我们抓个包,得到cookie值 base64解码 扫描一下靶机ip的目录 发现http://192.168.88.153/backup/,访问 下载一下发现是他的网页源码 通过代码审计,发现 通过代码审计得知&…...

类型推断技术及仓颉语言实践
史磊 仓颉语言类型推断技术专家 一、一种看待类型系统的方式 一门编程语言一定得包含类型系统吗? 这个问题今天看来可能显而易见,一个程序没有类型的话还能算是个完整、正确的程序吗?但是其实关于类型系统的作用,一直是存在两种…...

职场生存秘籍:16条黄金法则
作者简介:一名计算机萌新、前来进行学习VUE,让我们一起进步吧。 座右铭:低头赶路,敬事如仪 个人主页:我叫于豆豆吖的主页 写在前面 在这个瞬息万变的时代,职场不仅是实现个人价值与梦想的舞台,更是一…...

Flask 介绍
Flask 介绍 为什么要学 Flask框架对比设计哲学功能特点适用场景学习曲线总结 Flask 的特点Flask 常用扩展包Flask 的基本组件Flask 的应用场景官方文档官方文档链接文档内容概述学习建议 Flask 是一个使用 Python 编写的轻量级 Web 应用框架。它旨在让 Web 开发变得快速、简单且…...

JAVA基础知识点3 (String 和 StringBuffer 以及 StringBuilder 的特点以及区别)
1,String 和 StringBuffer 以及 StringBuilder 的特点 (1)String的特点:String是final修饰的字符序列是不可改变的, 是字符串常量,一旦初始化就不可以被更改,因此是线程安全的 因为是常量每次对其操作都会…...

2024年8月AI内容生成技术的现状与未来:从文生文到跨模态交互的全景分析
2024年8月AI内容生成技术的现状与未来:从文生文到跨模态交互的全景分析 大家好,我是猫头虎!🚀 随着AI在内容生成领域的爆发式发展,从2022年末开始,AI生成技术已经走过了文生文(AIGC)…...

File 34
package File;import java.awt.*; import java.io.File;public class file1 {public static void main(String[] args) {//创建FILE对象,指代某个具体的文件//路径分隔符File f1new File("C:/Users/SUI/Desktop/kaishi/nih.txt");// File f1new File(&quo…...
AI全知道-Embedding model中的Vector知识点
在嵌入模型(Embedding Model)中,向量(Vector)是核心概念之一。向量表示法不仅是数学中的基本工具,也是机器学习和深度学习中处理高维数据的关键手段。本文将深入探讨向量在嵌入模型中的作用、表示方法、计算和应用等知识点。 一、向量的基本概念 向量是一个具有方向和大…...

Qt 学习第四天:信号和槽机制(核心特征)
信号和槽的简介 信号和插槽用于对象之间的通信。信号和插槽机制是Qt的核心特征,可能是不同的部分大部分来自其他框架提供的特性。信号和槽是由Qt的元对象系统实现的。介绍(来自Qt帮助文档Signals & Slots) 在GUI编程中,当我们…...
跳跃游戏Ⅱ C++简单代码
给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回到达 nums[n - 1] 的最…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...