SpringBoot 整合ElasticSearch,实现站内搜索,高亮关键字

avatar 2019年2月6日11:02:06 2 1,621 views

ElasticSearch 是目前最风靡的开源框架之一,常用于站内搜索和日志分析。上一篇文章介绍了 ES 和 MySQL 数据同步,本文就介绍 ES 如何集成到 SpringBoot 中,实现基本的查询。

本文主要用于站内搜索,可实现智能分词,高亮关键字等功能,查询速度也很快。

本文采用 ElasticSearch 6.5.0,客户端是 Rest Client

一、整合 SpringBoot

1.pom.xml

  1. <!-- ElasticSearch -->
  2.    <dependency>
  3.      <groupId>org.elasticsearch</groupId>
  4.      <artifactId>elasticsearch</artifactId>
  5.      <version>6.5.0</version>
  6.    </dependency>
  7.    <!-- Java High Level REST Client -->
  8.    <dependency>
  9.      <groupId>org.elasticsearch.client</groupId>
  10.      <artifactId>elasticsearch-rest-high-level-client</artifactId>
  11.      <version>6.5.0</version>
  12.      <exclusions>
  13.        <exclusion>
  14.          <groupId>org.elasticsearch</groupId>
  15.          <artifactId>elasticsearch</artifactId>
  16.        </exclusion>
  17.      </exclusions>
  18.    </dependency>

 

2.配置类

ESConfig.java

  1. package com.liuyanzhao.sens.config;
  2. import org.apache.http.HttpHost;
  3. import org.elasticsearch.client.RestClient;
  4. import org.elasticsearch.client.RestHighLevelClient;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. /**
  8.  * ElasticSearch 配置类
  9.  * 实例化 client
  10.  *
  11.  * @author 言曌
  12.  * @date 2019/2/2 下午3:55
  13.  */
  14. @Configuration
  15. public class ESConfig {
  16.     @Bean
  17.     public RestHighLevelClient client() {
  18.         RestHighLevelClient client = new RestHighLevelClient(
  19.                 RestClient.builder(
  20.                         new HttpHost("localhost"9200"http")));
  21.         return client;
  22.     }
  23. }

主要用于创建 client,然后要用的地方只需要注入,而不是在方法里,每次 new 一个。

 

3. Controller 层

  1. @Autowired
  2.    private RestHighLevelClient client;
  3.    /**
  4.     * 搜索
  5.     *
  6.     * @param model model
  7.     * @param page  当前页码
  8.     * @return 模板路径/themes/{theme}/index
  9.     */
  10.    @GetMapping(value = "/search/page/{page}")
  11.    public String searchPage(Model model,
  12.                             @PathVariable(value = "page") Integer page,
  13.                             @RequestParam("keyword") String keyword) {
  14.        //默认显示20条
  15.        Integer size = 20;
  16.        //所有日志数据,分页
  17.        Page posts = new Page(page, size);
  18.       // Page<Post> posts = postService.searchByKeywords(HtmlUtil.escape(keyword), pageable);
  19.        page = page > 0 ? page : 0;
  20.        //search request
  21.        SearchRequest searchRequest = new SearchRequest("blog");
  22.        //search builder
  23.        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  24.        sourceBuilder.query(QueryBuilders.matchQuery("postTitle", keyword));
  25.        sourceBuilder.from((page - 1) * size);
  26.        sourceBuilder.size(size);
  27.        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
  28.        //sort
  29.        sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
  30.        //highlight
  31.        HighlightBuilder highlightBuilder = new HighlightBuilder();
  32.        HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("postTitle");
  33.        highlightTitle.preTags("<span class=\"highlight\">");
  34.        highlightTitle.postTags("</span>");
  35.        highlightBuilder.field(highlightTitle);
  36.        sourceBuilder.highlighter(highlightBuilder);
  37.        // add builder into request
  38.        searchRequest.indices("blog");
  39.        searchRequest.source(sourceBuilder);
  40.        //response
  41.        SearchResponse searchResponse = null;
  42.        try {
  43.            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
  44.        } catch (IOException e) {
  45.            e.printStackTrace();
  46.        }
  47.        TimeValue took = searchResponse.getTook();
  48.        //search hits
  49.        SearchHits hits = searchResponse.getHits();
  50.        long totalHits = hits.getTotalHits();
  51.        SearchHit[] searchHits = hits.getHits();
  52.        List<EsPost> postList = new ArrayList<>();
  53.        posts.setTotal((int) totalHits);
  54.        for (SearchHit hit : searchHits) {
  55.            String str = hit.getSourceAsString();
  56.            EsPost esPost = JSONObject.parseObject(str, EsPost.class);
  57.            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
  58.            HighlightField highlight = highlightFields.get("postTitle");
  59.            if (highlight != null) {
  60.                Text[] fragments = highlight.fragments();
  61.                String fragmentString = fragments[0].string();
  62.                esPost.setPostTitle(fragmentString);
  63.            }
  64.            postList.add(esPost);
  65.        }
  66.        posts.setRecords(postList);
  67.        model.addAttribute("is_index"true);
  68.        model.addAttribute("posts", posts);
  69.        model.addAttribute("prefix""/search");
  70.        model.addAttribute("suffix""?keyword=" + keyword);
  71.        model.addAttribute("time", took);
  72.        return this.render("search");
  73.    }

本例只是个 demo,主要关注其中23-75行。正常情况,需要把逻辑实现写在 Service 层

 

二、具体效果

css 样式

  1.     .highlight {
  2.         color: red;
  3.     }

 

比如搜 springboot入门

  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:2   其中:访客  2   博主  0

    • avatar Charrian 0

      学习到了!佩服博主 :wink: :wink:

      • avatar 人工智能技术 1

        ElasticSearch这个开源程序挺好的