校园课程助手【4】-使用Elasticsearch实现课程检索

news2024/11/15 14:02:29

本节将介绍本项目的查询模块,使用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 {

    @Id
    private 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 field
    public 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);
    @Autowired
    private EsProductDao esProductDao;
    @Autowired
    private EsProductRepository esProductRepository;
    @Override
    public 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;
    }

    @Override
    public void delete(Long id) {
        logger.info("删除ES中的商品{}:",id);
        esProductRepository.deleteById(id);
    }

    @Override
    public 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);
    }

    @Override
    public 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_stock
        FROM course
    </select>

</mapper>

7.在controller包下新建控制器EsProductController


/**
 * ES搜索课程Controller
 **/
@Controller
@Api(tags = "EsProductController",description = "ES课程搜索")
public class EsProductController {
    @Autowired
    private EsProductService esProductService;

    @ApiOperation("从数据库导入ES课程数据")
    @RequestMapping(value = "/esProduct/importAll",method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<Integer> importAll(){
        int count = esProductService.importAll();
        return CommonResult.success(count);
    }

    @ApiOperation("根据id删除课程")
    @RequestMapping(value = "/esProduct/delete/{id}",method = RequestMethod.POST)
    @ResponseBody
    public CommonResult deleteById(@PathVariable Long id){
        esProductService.delete(id);
        return RespBean.success("删除成功");
    }

    @ApiOperation("批量删除课程")
    @RequestMapping(value = "/esProduct/deletes",method = RequestMethod.POST)
    @ResponseBody
    public CommonResult deleteById(List<Long> ids){
        esProductService.deletes(ids);
        return RespBean.success("删除成功");
    }

    @ApiOperation("根据id创建课程")
    @RequestMapping(value = "/esProduct/create",method = RequestMethod.POST)
    @ResponseBody
    public 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)
    @ResponseBody
    public 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));
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1970817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

​EtherCAT、CANopen、RS485在电机控制中的对比

​EtherCAT、CANopen、RS485在电机控制中的对比 EtherCAT 特点&#xff1a; 高速通信&#xff1a;EtherCAT是一种实时以太网技术&#xff0c;数据传输速度快&#xff0c;具有极低的通信延迟和抖动。 高同步性&#xff1a;可精确同步多台设备&#xff0c;适用于高要求的控制任…

Python爬虫技术 第23节 数据清洗和预处理

在使用Python进行网络爬虫项目时&#xff0c;数据清洗和预处理是非常重要的步骤。这些步骤有助于确保从网页上抓取的数据准确、一致&#xff0c;并且适合后续的分析或机器学习任务。下面我将详细介绍如何使用Python来进行数据清洗和预处理。 1. 数据获取 首先&#xff0c;你需…

Java 实现 AVL树

在二叉平衡树中&#xff0c;我们进行插入和删除操作时都需要遍历树&#xff0c;可见树的结构是很影响操作效率的。在最坏的情况下&#xff0c;树成了一个单支树&#xff0c;查找的时间复杂度成了O(N)&#xff0c;建树跟没建树一样。那么是不是有什么办法可以建一个树避免这种情…

基于 KubeSphere 的 Kubernetes 生产环境部署架构设计及成本分析

转载&#xff1a;基于 KubeSphere 的 Kubernetes 生产环境部署架构设计及成本分析 前言 导图 1. 简介 1.1 架构概要说明 今天分享一个实际小规模生产环境部署架构设计的案例&#xff0c;该架构设计概要说明如下&#xff1a; 本架构设计适用于中小规模(<50)的 Kubernetes …

本地生活服务商公司有哪些?一文教你搭建本地生活系统!

当前&#xff0c;本地生活领域群雄环伺&#xff0c;日益激烈的竞争推动各家互联网大厂调整布局模式的同时&#xff0c;也让本地生活市场持续迸发新的活力。在此背景下&#xff0c;想要通过本地生活服务商身份入局的创业者数量不断增多&#xff0c;以本地生活服务商公司有哪些等…

前端面试题整理-CSS

两栏布局 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>两栏布局</title><style>…

java计算机毕设课设—基于网络爬虫技术的网络新闻分析系统(附源码、文章、相关截图、部署视频)

这是什么系统&#xff1f; java计算机毕设课设—基于网络爬虫技术的网络新闻分析系统 基于网络爬虫技术的新闻分析系统&#xff0c;它能够实时抓取凤凰网、网易、新浪、搜狐等网站的新闻数据&#xff0c;提取正文和点击量&#xff0c;每日定时抓取。系统还能对抓取的新闻进行…

给echarts图表线条、数据点和区域设置颜色

let myChart echarts.init(document.getElementById("chartmainCop"));// 获取当前干部的各项评分const allIndicators Object.keys(this.dialogEacherTable[0]).filter(key > key ! "CadreID" && key ! "xm").map(key > ({name…

window电脑上使用python将pdf转换为word文档

1、电脑上安装Python运行环境 一、python官网下载链接 二、下载到电脑后&#xff0c;直接运行安装 三、安装完成后按&#xff1a;winR键进入window命令控制窗口&#xff0c;输入 python --version2、设置python依赖包国内镜像源 pip config set global.index-url https://mirr…

国家发改委区域司韩振海副司长一行莅临麒麟信安调研

7月31日&#xff0c;国家发改委区域司韩振海副司长一行莅临麒麟信安调研。湖南省发改委区域处处长孙健军&#xff0c;长沙市发改委党组成员、市长株潭一体化发展事务中心主任邹犇淼等相关领导陪同调研。麒麟信安总裁刘文清热情接待。 在麒麟信安展厅&#xff0c;韩振海副司长一…

在MANET中的TCP增强

本文内容节选自一篇系统性文献综述&#xff08;Systematic Literature Review, SLR&#xff09;&#xff0c;标题为“TCP Performance Enhancement in IoT and MANET”&#xff0c;由 Sultana Parween 和 Syed Zeeshan Hussain 撰写&#xff0c;发表在《International Journal …

Windows下Rust OpenCV环境配置

首发于Enaium的个人博客 安装Chocolatey 首先我们需要安装Chocolatey&#xff0c;Chocolatey是一个Windows的包管理器。 我们点击右上角的Install进入到Installing Chocolatey&#xff0c;选择Individual 复制命令 Set-ExecutionPolicy Bypass -Scope Process -Force; [Sys…

springboot餐饮管理系统-计算机毕业设计源码73168

摘要 随着科技的不断进步和互联网时代的深入发展&#xff0c;餐饮行业正面临着一场由传统向智能化、信息化转变的革命。传统的餐饮管理方式&#xff0c;如手工点餐、纸质菜单、人工结算等&#xff0c;已经无法满足现代餐饮企业对于效率、准确性和用户体验的高要求。因此&#x…

【Hot100】LeetCode—31. 下一个排列

目录 题目1- 思路2- 实现⭐31. 下一个排列——题解思路 3- ACM 实现 题目 原题连接&#xff1a;31. 下一个排列 1- 思路 技巧题&#xff0c;分为以下几个步骤 ① 寻找拐点&#xff1a; i 1 &#xff1a;出现 nums[i1] > nums[i] &#xff0c;则 i 1 就是拐点 从右向左遍…

技术守护尊严||Chat GPT在抵抗性骚扰的作用分析

就在本周&#xff0c;中国人民大学女博士实名举报导师性骚扰的事情&#xff0c;引发全网关注&#xff01; 性骚扰&#xff0c;无论在线上还是线下&#xff0c;无论在职场还是校园&#xff0c;都是对个人尊严与权益的严重侵犯。 幸运的是&#xff0c;随着人工智能技术的飞速发…

专题九_链表(1)

目录 题型总结 2. 两数相加 解析 题解 24. 两两交换链表中的节点 解析 题解 题型总结 2. 两数相加 2. 两数相加 解析 题解 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr)…

硬件开发笔记(二十九):TPS54331电源设计(二):12V转3.3V和12V转4V原理图设计

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140868749 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

一款功能强大且免费的跨平台图片批量处理工具

XnConvert是一款功能强大且免费的跨平台图片批量处理工具&#xff0c;广泛应用于个人用户、教育机构和非营利组织。它支持超过500种图片格式&#xff0c;包括常见的JPEG、PNG、TIFF、GIF、WebP、PSD、JPEG2000等&#xff0c;并能够导出为大约70种不同的文件格式。 该软件的主要…

【云原生】kubernetes弃用docker之后,containerd何以承载云原生?

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Mac OS平台,利用 gifify 制作gif教程

一、前言 在很多时候都会用到视频的方式才能直观的表达想表达的东西&#xff0c; 但是视频的文件太大了&#xff0c;所以gif是一个很不错的选择&#xff0c;在网上找了很多免费的都不好用&#xff0c; 最理想的还是直接快捷键唤起&#xff0c;然后选择录制区域&#xff0c;保存…