zoukankan      html  css  js  c++  java
  • Spring boot 论坛项目实战_06

    Elasticsearch,分布式搜索引擎

    目前性能最好的搜索引擎

    1. Elasticsearch入门

    • Elasticsearch简介

      • 一个分布式的、Restful风格的搜索引擎

        • 分布式:多台服务器、集群式部署

        • Restful:设计风格,规定前后端交互方式

      • 支持对各种类型的数据的检索

      • 搜索速度快,可以提供 实时 的搜索服务

      • 便于水平扩展,每秒可以处理PB级海量数据

    • Elasticsearch术语【mysql中相对对象】

      • 索引【库】、类型【表】、文档{json结构}【一行数据】、字段{json中一个属性}【一列】

        • 6.0 版本后,类型逐渐被废弃,索引对应【表】,类型被固定成一个单词

        • 7.0 版本后,类型彻底被废弃

      • 集群、节点【某一台服务器】、分片【对这个索引的进一步划分、提高并发能力】、副本【对分片的备份】

    • 参考网站:

     

    Elasticsearch安装

    • 务必考虑自身当前的 Spring 与 Elasticsearch 兼容问题, 选择合适的版本

    • 本次环境使用的 Elasticsearch 版本为 6.4.3

    配置 ES 相关属性:

    • Config/elasticsearch.yml 文件

    • 配置集群名字:自定义,这里自定为 nowcoder

    • 配置文件存储位置、日志存放位置:

    配置环境变量【Windows 平台】

    • 往Path 中添加解压后ES 的 bin目录即可

     

    安装中文分词软件

    • Github 搜索: elasticsearch ik

    • 选择和你安装的 ES 对应的 ik 版本

    • 下载第一个 zip 即可

    • 文件必须解压到 ESpluginsik 目录下

    • 将分词 ik 直接解压到 ik 文件目录下:

    • 更新网络新词 配置:

    安装 Postman【可选】

    • 一个web 模拟工具

     

    常用命令访问 ES【查询健康状态、查询节点、查询索引、新增索引、删除索引】

    记得先去 ES 的 bin 下 启动 elasticsearch.bat 服务

     

    2. Spring 整合 Elasticsearch

    • 引入依赖

      • spring-boot-starter-data-elasticsearch

    • 配置Elasticsearch

      • cluster-name、cluster-nodes

    • Spring Data Elasticsearch

      • ElasticsearchTemplate

      • ElasticsearchRepository

     

    运行时报错::

    NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{127.0.0.1}{127.0.0.1:9300}]]

    • 解决方法:

      • 修改 elasticsearch.yml

      • 修改服务器地址, 记得把 http 的端口放出来, java 运行的是 FTP 的 9300 端口

     

    • Java 实现 ES 查询方法:

      • // 搜索功能
        // withQuery: 【搜索条件】
        // withSort: 【排序条件】
        // withPageable:【分页条件】
        // withHighlightFields :【指定高亮显示】
        // build() 执行方法, 生成 SearchQuery 对象实现类
          @Test
           public void testSearchByRespository(){
               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))//of(第几页,显示条数)
                      .withHighlightFields(
                               new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
                               new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
                      ).build();

               // Page: 是这个方法提供的对象,不是我们自定义的
               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);
              }
          }
    • 用Template 处理高亮显示

      •  @Test
            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))//of(第几页,显示条数)
                        .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> clazz, 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.setTitle(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);
                }
        ​
            }
      • 可以看到,现在运行结果中,关键词是带了标签的

     

    3. 开发社区搜索功能

    • 搜索服务

      • 将帖子保存至 Elasticsearch 服务器

      • 从 Elasticsearch 服务器删除帖子

      • 从 Elasticsearch 服务器搜索帖子

    • 发布事件

      • 发布帖子时候,将帖子异步的提交到 Elasticsearch 服务器

      • 增加评论时,将帖子异步的提交到 Elasticsearch 服务器

      • 在消费组件中增加一个方法,消费帖子发布事件

    • 显示结果

      • 在控制器中处理搜索请求,在 HTML 上显示搜索结果

  • 相关阅读:
    ES6常用语法
    @Autowired和@Resource的区别
    spring boot 引导
    Springboot 日志管理配置logback-spring.xml
    Java异常之checked与unchecked
    @Transactional(rollbackFor=Exception.class)的使用
    使用spring @Scheduled注解执行定时任务、
    Spring入门学习推荐
    Hadoop调优
    关于Flink--ProcessFunction的使用
  • 原文地址:https://www.cnblogs.com/77-is-here/p/13713099.html
Copyright © 2011-2022 走看看