社区系统项目复盘-6

news2024/11/27 3:54:42

文章目录

      • 什么是Elasticsearch?
      • Spring是怎么整合Elasticsearch的?
      • 开发社区搜索功能

Elasticsearch实现全文搜索功能

什么是Elasticsearch?

  • Elasticsearch简介

    • 一个分布式的、Restful风格的搜索引擎
    • 支持对各种类型的数据的检索
    • 搜索速度快,可以提供实时的搜索服务
    • 便于水平扩展,可以处理PB级海量数据
  • Elasticsearch术语

    • 索引、类型、文档、字段 (与 mysql中的数据库、表、行、列相对应,ES7.0以后,废弃掉了类型的概念,索引对应表,文档对应行,字段对应列)
    • 集群、节点、分片、副本
  • Elasticsearch的下载安装

    下载elasticsearch安装包,解压缩。修改config/elasticsearch.yml文件中的cluster.name、path.data、path.logs。下载ik中文分词器(springboot、elasticsearch、ik 版本要对应),在plugins文件夹下创建名为ik的文件夹,将下载的中文分词器解压缩到新建的ik文件夹下。执行 ./bin/elasticsearch启动ES服务。

Spring是怎么整合Elasticsearch的?

第一步:引入依赖

  • spring-boot-starter-data-elasticsearch
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

第二步:配置Elasticsearch

  • cluster-name、cluster-nodes
# ElasticsearchProperties
spring.data.elasticsearch.cluster-name=amelia # 这个就是es配置文件中配置的cluster.name
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300

⚠️ :elasticsearch有两个默认端口,9200是http访问,9300是tcp访问
⚠️:由于redis和es底层都使用了netty,所以会有netty启动冲突的问题,需要在启动类中进行一些配置,详见 CommunityApplication

@PostConstruct
public void init(){
	// 解决netty启动冲突的问题
	// Netty4Utils.setAvailableProcessors()
	System.setProperty("es.set.netty.runtime.available.processors","false");
}

第三步:调用Spring提供的关于ES的API,访问ES服务器(Spring Data Elasticsearch)

  • ElasticsearchTemplate(类)

  • ElasticsearchRepository(接口)——这种方案更简单一点,优先选择这个

  • 示例:

    • 对实体类添加@Ducument注解,对实体中的属性也需要添加注解
    // 示例
    @Document(indexName = "discusspost",type = "_doc",shards = 6,replicas = 3)
    public class DiscussPost {
        @Id
        private int id;
        @Field(type = FieldType.Integer)
        private int userId;
        @Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
        private String title;
        @Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
        private String content;
        @Field(type = FieldType.Integer)
        private int type;
        @Field(type = FieldType.Integer)
        private int status;
        @Field(type = FieldType.Date)
        private Date createTime;
        @Field(type = FieldType.Integer)
        private int commentCount;
        @Field(type = FieldType.Double)
        private double score;
    }
    
    • 定义ESRepository接口
    @Repository
    public interface DiscussPostRepository extends ElasticsearchRepository<DiscussPost,Integer> { //DiscussPost是数据的类型,Integer是主键的类型
    
    }
    
    • 使用 定义的接口 调用函数操作es服务器(对es服务器中的数据进行增删)
    // 示例
    // 添加一条数据
    discussRepository.save(discussPostMapper.selectDiscussPostById(241));
    // 添加一组数据
    discussRepository.saveAll(discussPostMapper.selectDiscussPosts(101,0,100,0));
    // 修改数据
    DiscussPost post = discussPostMapper.selectDiscussPostById(231);
    discussRepository.save(post);
    // 删除一条数据
    discussRepository.deleteById(231);
    // 删除全部数据
    discussRepository.deleteAll();
    
    • 搜索,利用定义的接口进行搜索。首先需要构造搜索的条件(利用SearchQuery接口),然后使用接口的search方法查询结果。
    // 示例
    public void testSearchByRepository(){
            SearchQuery searchQuery = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.multiMatchQuery("互联网寒冬","title","content"))
                    .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
                    .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
                    .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
                    .withPageable(PageRequest.of(0,10))
                    .withHighlightFields(
                            new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
                            new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
                    ).build();
            // elasticTemplate.queryForPage(searchQuery,class,SearchResultMapper)
            // 底层获取得到了高亮显示的值,但是没有返回
            Page<DiscussPost> page = discussRepository.search(searchQuery);
            System.out.println(page.getTotalElements());
            System.out.println(page.getTotalPages());
            System.out.println(page.getNumber());
            System.out.println(page.getSize());
            for(DiscussPost post : page){
                System.out.println(post);
            }
        }
    
    • 搜索,利用elasticTemplate进行搜索。(首先需要构造搜索的条件,然后进行结果查询,对搜索得到的结果要做一个处理,实现高亮显示)
    // 示例
    public void testSearchByTemplate(){
            SearchQuery searchQuery = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.multiMatchQuery("互联网寒冬","title","content"))
                    .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
                    .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
                    .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
                    .withPageable(PageRequest.of(0,10))
                    .withHighlightFields(
                            new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
                            new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
                    ).build();
    
            Page<DiscussPost> page = elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {
                @Override
                public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
                    SearchHits hits = response.getHits();
                    if(hits.getTotalHits() <= 0){
                        return null;
                    }
                    List<DiscussPost> list = new ArrayList<>();
                    for(SearchHit hit:hits){
                        DiscussPost post = new DiscussPost();
    
                        String id = hit.getSourceAsMap().get("id").toString();
                        post.setId(Integer.valueOf(id));
    
                        String userId = hit.getSourceAsMap().get("userId").toString();
                        post.setUserId(Integer.valueOf(userId));
    
                        String title = hit.getSourceAsMap().get("title").toString();
                        post.setTitle(title);
    
                        String content = hit.getSourceAsMap().get("content").toString();
                        post.setContent(content);
    
                        String status = hit.getSourceAsMap().get("status").toString();
                        post.setStatus(Integer.valueOf(status));
    
                        String createTime = hit.getSourceAsMap().get("createTime").toString();
                        post.setCreateTime(new Date(Long.valueOf(createTime)));
    
                        String commentCount = hit.getSourceAsMap().get("commentCount").toString();
                        post.setCommentCount(Integer.valueOf(commentCount));
    
                        // 处理高亮显示的结果
                        HighlightField titleField = hit.getHighlightFields().get("title");
                        if(titleField != null){
                            post.setTitle(titleField.getFragments()[0].toString());
                        }
                        HighlightField contentField = hit.getHighlightFields().get("content");
                        if(contentField != null){
                            post.setContent(contentField.getFragments()[0].toString());
                        }
    
                        list.add(post);
    
                    }
                    return new AggregatedPageImpl(list,pageable,
                            hits.getTotalHits(),response.getAggregations(),response.getScrollId(),hits.getMaxScore());
                }
            });
    
            System.out.println(page.getTotalElements());
            System.out.println(page.getTotalPages());
            System.out.println(page.getNumber());
            System.out.println(page.getSize());
            for(DiscussPost post : page){
                System.out.println(post);
            }
        }
    

开发社区搜索功能

  • 搜索服务

    • 发布帖子的时候,将帖子保存至Elasticsearch服务器。
    • 从Elasticsearch服务器删除帖子。
    • 从Elasticsearch服务器搜索帖子
  • 采用事件的方式来处理,发布事件

    • 发布帖子时,将帖子异步的提交到Elasticsearch服务器
    • 增加评论时,将帖子异步的提交到Elasticsearch服务器
    • 在消费组件中增加一个方法,消费帖子发布事件
  • 显示结果

    • 在控制器中处理搜索请求,在HTML上显示搜索结果
  • 实现细节:

    • 首先,要对entity中的实体类discusspost进行一些注解,在数据访问层创建一个DiscussPostRepository的接口,service层创建一个elasticsearch的服务类(ElasticsearchService),在表现层创建一个SearchController类,处理搜索功能。

    • 然后,在EventConsumer中创建一个消费发帖的事件【这个事件,主要就是用于把帖子存到Elasticsearch中】,分别在CommentController的发布评论方法和DiscussPostController的发布帖子方法中添加触发 发帖事件 的代码段。

    • 还有一点需要注意,由于redis和es底层都使用了netty,所以会有netty启动冲突的问题,需要在启动类中进行一些配置,详见 CommunityApplication

      在这里插入图片描述

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

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

相关文章

FSR-Unity-URP 1.0 的性能和兼容性问题

1&#xff09;FSR-Unity-URP 1.0 的性能和兼容性问题 ​2&#xff09;计算大文件MD5耗时问题 3&#xff09;如何监听Unity即将Reload Script 4&#xff09;如何对Unity游戏的Android崩溃和ANR问题进行符号化解析 这是第315篇UWA技术知识分享的推送。今天我们继续为大家精选了若…

2022年GPS广播星历精密星历如何下载

注意&#xff1a;&#xff01;&#xff01;网上现有很多教程的星历下载地址 ftp://cddis.gsfc.nasa.gov/已经访问不了了&#xff0c;最新的方法见下文&#xff0c;亲测有效~ 1、星历下载网址&#xff08;需要注册一下&#xff09;Earthdata Loginhttps://cddis.nasa.gov/archiv…

我的居家生活--爱摸鱼的美工(二)

-----------作者&#xff1a;天涯小Y 这失败的拉花叫”海上升明月” 呜一 做自己&#xff0c;不太好也没关系 我给自己居家的时间不多了 11月30日我决定”解封” 从身心开始&#xff0c;愿脚步跟上 突如其来的“银丝” 让我沮丧 黑芝麻的疗法因快递又安排不上 算了.幼笑吧 白发…

C#线程的参数传递、获取线程返回值以及处理多线程冲突

C#作为一门优秀的开发语言&#xff0c;现在国内的流行度貌似不如以前&#xff0c;大家都不在意它的无所不能了。 C#的灵活与强大只有在经常使用中才会有所领悟&#xff0c;适当地掌握它还是有必要的。 在这里总结一下线程的传递参数以及获取线程的返回值&#xff0c;还有处理多…

【毕业设计】17-基于单片机的矿井提升机_步进电机控制装置设计(原理图+仿真+源代码+实物图+答辩论文+答辩PPT)

typora-root-url: ./ 【毕业设计】17-基于单片机的矿井提升机_步进电机控制装置设计&#xff08;原理图仿真源代码实物图答辩论文答辩PPT&#xff09; 文章目录typora-root-url: ./【毕业设计】17-基于单片机的矿井提升机_步进电机控制装置设计&#xff08;原理图仿真源代码实…

IB中文(语言与文学)介绍分析

Intro to Group 1 Subjects&#xff1a;语言A 语言A科目主要针对学生的母语语言运用与文学鉴赏能力进行考核&#xff0c;旨在培养学生文学素养的同时注重社会关怀、全球视角与批判性思维的意识形成。 IB文凭要求每位学生至少在语言A中学习一门课程。 今天我们就来仔细介绍一下其…

全波形反演的深度学习方法: 第三章 常规反演

本章介绍反演的基础知识, 以及工程中的常规反演. 仅供内部培训. 3.1 地震数据采集 地震勘探中常使用人工激发的振动进行数据采集. 相应装置包括: 激发器是产生震动的装置, 如炸药, 地震车 (撞击地面). 在城市道路等具有车辆会产生振动的地方, 也可以不安装这类装置;地震检波…

为什么我推荐用户故事地图?

最近在给几个客户的培训和辅导中&#xff0c;都用到了用户故事地图(User Story Mapping or USM)&#xff0c;越来越发现USM是一个强大的工具。USM有它特殊的妙用之处和适用范围&#xff0c;我们不用指望USM能解决多的问题&#xff0c;比如产品架构和用户体验旅程就不在USM的范围…

TSN新技术,让您的设备网络“更实时、更确定、更安全”

近日,工业和信息化部发布了2022年第23号公告,批准发布行业标准YD/T 4134-2022《工业互联网时间敏感网络需求及场景》。该标准是国内首个时间敏感网络(TSN)技术标准,标志着我国TSN技术标准体系建设迈出了坚实的一步,对构建工业互联网网络标准体系具有重要意义。 TSN源于Time…

【解决方法】错误:无法和SFTP服务器建立FTP连接,请选择合适的协议

在家连实验室的服务器时&#xff0c;出现了如下的情况&#xff1a;当时一直在想为啥协议不合适。 解决方案&#xff1a; 1. 点击【文件】->【站点管理器】&#xff0c;出现如下界面&#xff1a; 可能你的那里没有新站点&#xff0c;如果没有就点击新站点哦。 2. 点击【协议…

社区系统项目复盘-4

文章目录Redis高性能存储什么是Redis&#xff1f;为什么使用Redis&#xff1f;Spring是怎么整合Redis的&#xff1f;Redis事务管理点赞关注优化登录模块Redis高性能存储 使用redis实现了点赞、关注相关的功能&#xff0c;优化了登录模块。 什么是Redis&#xff1f; Redis是一…

[附源码]计算机毕业设计springboot基于vue的软件谷公共信息平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

力扣(LeetCode)895. 最大频率栈(C++)

设计 ①维护最大频率&#xff0c;②维护每个数的出现次数&#xff0c;③维护出现次数对应的栈。 压栈时&#xff0c;新数压入出现次数对应的栈&#xff0c;每次压入新数&#xff0c;维护最大频率(所有出现次数中的最大出现次数)。 弹栈时&#xff0c;找最大频率对应的栈&…

RealEvo许可证协议

一直使用RealEvo V4.0.0版&#xff0c;今天因license到期&#xff0c;索性一同安装下新版的IDE。 当前最新RealEvo IDE版本为 V5.0.5&#xff0c;V5.0.0~V5.0.3版本存在一些bug&#xff0c;建议更新。 SylixOS 许可信息如下&#xff08;开源版本&#xff09; SylixOS嵌入式实…

【毕业设计】前后端分离——实现登录注册功能

&#x1f308;据说&#xff0c;看我文章时 关注、点赞、收藏 的 帅哥美女们 心情都会不自觉的好起来。 前言&#xff1a; &#x1f9e1;作者简介&#xff1a;大家好我是 user_from_future &#xff0c;意思是 “ 来自未来的用户 ” &#xff0c;寓意着未来的自己一定很棒~ ✨个…

Word控件Spire.Doc 【图像形状】教程(8): 如何借助C#/VB.NET在 Word 中插入艺术字

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

基于51单片机的智能蓝牙路灯街灯控制系统proteus仿真原理图PCB

功能&#xff1a; 0.本系统采用STC89C52作为单片机 1.液晶实时显示时间/环境光强/工作模式 2.每隔5s向蓝牙串口发送一次信息 3.支持路灯故障检测 4.工作时间18~24时&#xff0c;两个路灯同时点亮&#xff0c;24时以后&#xff0c;B路灯关闭&#xff0c;若检测到由物体通过&…

【Kafka】Kafka的重复消费和消息丢失问题

文章目录前言一、重复消费1.1 重复消费出现的场景1.1.1 Consumer消费过程中&#xff0c;进程挂掉/异常退出1.1.2 消费者消费时间过长1.2 重复消费解决方案1.2.1 针对于消费端挂掉等原因造成的重复消费问题1.2.2 针对于Consumer消费时间过长带来的重复消费问题二、消息丢失2.1 生…

Multipass,多平台本地轻量级Linux体验!

Multipass 是由Ubuntu官方提供&#xff0c;在Linux&#xff0c;MacOS和Windows上快速生成 Ubuntu虚拟机 的工具。它提供了一个简单但功能强大的CLI&#xff0c;可让我们在本地快速进入Ubuntu系统环境并使用Linux命令&#xff0c;亦可以在本地计算机创建自己的迷你型云服务器。总…

zabbix监控网络连接状态

目录 一、环境准备 二、网络连接状态介绍 三、自定义监控key 四、给主机添加监控项 一、环境准备 1、搭建zabbix基础环境 zabbix基础环境部署参照&#xff1a;zabbix基础环境部署_桂安俊kylinOS的博客-CSDN博客 2、给web1安装nginx环境&#xff0c;并加载status模块 以…