牛客社区项目中SpringBoot集成ElasticSearch 6.XX改为ElasticSearch 7.17所遇到的问题

494 阅读2分钟

情况说明

开发牛客社区项目中,原教程视频使用ElasticSearch 6.XX,现需要集成ElasticSearch 7.XX,由于版本变更导致使用差别太大,记录一些自己遇到的问题和解决方案。

使用的Springboot为2.7.4,使用的ElasticSearch版本为7.17.6

问题1

问题:SpringBoot自动注入ElasticsearchTemplate失败。

原因:SpringBoot集成ElasticSearch 7.17中已经弃用ElasticsearchTemplate,只能使用ElasticsearchRestTemplate

解决方法:将ElasticsearchTemplate修改为ElasticsearchRestTemplate

问题2

问题:ElasticsearchRepository不再拥有search()方法,只剩下了searchSimilar()方法。

解决方法:没有什么解决方法,不能像教程中那样使用ElasticsearchRepository做复杂的查询了。

问题3

问题:ElasticsearchRestTemplate的使用方法和ElasticsearchTemplate不同,如何使用ElasticsearchRestTemplate实现和教程中一样复杂的查询任务。

解决方法:使用以下代码可以完成和教程中一样的功能,参考自课程评论区。

@Test
public void testSearchByTemplate() {
    // 高亮条件
    HighlightBuilder highlightBuilder = new HighlightBuilder()
            .field("title") // 给哪些自动设置高亮
            .field("content") 
            .requireFieldMatch(false)
            .preTags("<em>") // 匹配到的字段间要加的内容
            .postTags("</em>"); // 匹配到的字段后要加的内容
    // 构建搜索条件
    NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content"))
            .withSorts(SortBuilders.fieldSort("type").order(SortOrder.DESC))
            .withSorts(SortBuilders.fieldSort("score").order(SortOrder.DESC))
            .withSorts(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
            .withPageable(PageRequest.of(0, 10))
            .withHighlightBuilder(highlightBuilder).build();
    SearchHits<DiscussPost> search = elasticsearchRestTemplate.search(searchQuery, DiscussPost.class);
    SearchPage<DiscussPost> page = SearchHitSupport.searchPageFor(search, searchQuery.getPageable());
    System.out.println(page.getTotalElements());
    System.out.println(page.getTotalPages());
    System.out.println(page.getNumber());
    System.out.println(page.getSize());
    for (SearchHit<DiscussPost> discussPostSearchHit : page) {
        System.out.println(discussPostSearchHit.getHighlightFields()); // 高亮的内容
        System.out.println(discussPostSearchHit.getContent()); // 原始的DiscussPost
    }
    // 将带有高亮内容的DiscussPost封装到page对象中
    // 其实可以不封装到 page ,在业务中我们直接用List就可以实现功能。
    List<DiscussPost> list = new ArrayList<>();
    for (SearchHit<DiscussPost> discussPostSearchHit : page) {
        DiscussPost discussPost = discussPostSearchHit.getContent();
        if (discussPostSearchHit.getHighlightFields().get("title") != null) {
            discussPost.setTitle(discussPostSearchHit.getHighlightFields().get("title").get(0));
        }
        if (discussPostSearchHit.getHighlightFields().get("content") != null) {
            discussPost.setContent(discussPostSearchHit.getHighlightFields().get("content").get(0));
        }
        list.add(discussPost);
    }

    Page<DiscussPost> pageInfo = new PageImpl<>(list, searchQuery.getPageable(), search.getTotalHits());
    System.out.println(pageInfo.getTotalElements());
    System.out.println(pageInfo.getTotalPages());
    System.out.println(pageInfo.getNumber());
    System.out.println(pageInfo.getSize());
    for (DiscussPost discussPost : pageInfo) {
        System.out.println(discussPost);
    }
}

总的来说,原理和教程中差别不大,代码实现上出现了差别,但是变得更加容易了,理解起来也更加简单,困难点在于api发生了变化。

其他注意点

Springboot 2.7.4集成ElasticSearch 7.17.6

配置文件中不必再写教程中的那些配置了,教程中的已经不推荐使用或者弃用了。

同时也不需要处理Netty冲突的问题了。教程中展现的那些类大部分已经没有了。

并没有系统的学习过ElasticSearch,针对项目中遇到的问题和解决方法做总结,原理上如有不足之处求指教。