社区系统项目复盘-6
创始人
2024-03-02 17:45:57
0

文章目录

      • 什么是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
org.springframework.bootspring-boot-starter-data-elasticsearch

第二步:配置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 {@Idprivate 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是主键的类型}
    
    • 使用 定义的接口 调用函数操作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("").postTags(""),new HighlightBuilder.Field("content").preTags("").postTags("")).build();// elasticTemplate.queryForPage(searchQuery,class,SearchResultMapper)// 底层获取得到了高亮显示的值,但是没有返回Page 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("").postTags(""),new HighlightBuilder.Field("content").preTags("").postTags("")).build();Page page = elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {@Overridepublic  AggregatedPage mapResults(SearchResponse response, Class aClass, Pageable pageable) {SearchHits hits = response.getHits();if(hits.getTotalHits() <= 0){return null;}List 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

      在这里插入图片描述

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...