• spring boot 2.7.X下使用elastic


    说明:
    由于elastic 更新较快,这里只介绍spring boot 集成的elastic7.17.4 ,如果想直接使用elastic8,推荐你再搜搜别的
    本文章大概可以坚持到2024年(如果更新会往后推)
    没有2.7版本可以试着升一下spring boot2升级至2.7.3环境配置

    这里使用的是ElasticsearchRestTemplate

    RestHighLevelClient 已弃用
    ElasticsearchRepository已弃用

    1. 引入elastic

    <dependency>
    	<groupId>org.springframework.bootgroupId>
    	<artifactId>spring-boot-starter-data-elasticsearchartifactId>
    	<version>2.7.3version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. Yml配置

    注意了,当前版本就是这个,原来的版本要注意会存在多字段

    spring:
      elasticsearch:
        uris: 192.168.2.91:9200
        #username:
        #password:
        #connection-timeout: 1
        #read-timeout: 30 默认30
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3. 创建MyUser实体类

    需要注意大小写以及下划线转换

    import lombok.Data;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.elasticsearch.annotations.Document;
    
    /**
     * @author king
     */
    @Data
    @Document(indexName = "my_user")
    public class MyUser {
        @Id
        private String id;
        private String username;
        private String password;
        private String realname;
        private String nickname;
        private String file;
    	// 这里没用到
        public MyUser(String id, String username, String password,String realname, String nickname, String file) {
            this.id = id;
            this.username = username;
            this.password = password;
            this.realname = realname;
            this.nickname = nickname;
            this.file = file;
        }
        public MyUser() {
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    4. 创建 service

    这里贴一个我自己写的util,可以直接用在service里

    import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
    import org.springframework.data.elasticsearch.core.IndexOperations;
    import org.springframework.data.elasticsearch.core.SearchHits;
    import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    import java.util.Collection;
    
    /**
     * @author king
     * 2022-08-23
     * 此方法适用于 spring boot 2.7.X 以及spring boot 当前版本集成下的elastic-7.17.4
     * 涵盖sprng-data-elasticsearch-4.4.2
     */
    @Component
    public class ElasticUtils {
        @Resource
        ElasticsearchRestTemplate elasticsearchRestTemplate;
    
        /**
         * 新增索引(表)
         */
        public <T> Boolean put(T entity) {
            IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(entity.getClass());
            return indexOperations.create();
        }
    
        /**
         * 判断索引是否存在
         */
        public <T> Boolean exists(T entity) {
            IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(entity.getClass());
            return indexOperations.exists();
        }
    
        /**
         * 删除索引
         */
        public <T> Boolean delete(T entity) {
            IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(entity.getClass());
            return indexOperations.delete();
        }
    
        /**
         * 修整索引字段(与实体类保持一致,一般为增加,减少字段未测试)
         */
        public <T> Boolean mapping(T entity) {
            IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(entity.getClass());
            return indexOperations.putMapping();
        }
        /**
         * 插入
         */
        public <T> T save(T entity) {
            return elasticsearchRestTemplate.save(entity);
        }
        /**
         * 批量插入
         */
        public Iterable saveBatch(Collection collectors) {
            return elasticsearchRestTemplate.save(collectors);
        }
        /**
         * 根据主键查询
         */
        public <T> Object get(String id, T entity) {
            return elasticsearchRestTemplate.get(id, entity.getClass());
        }
        /**
         * 根据主键删除
         */
        public <T> String delete(String id, T entity) {
            return elasticsearchRestTemplate.delete(id, entity.getClass());
        }
        /**
         * 多条件查询
         */
        public <T> SearchHits<?> search(T entity, NativeSearchQueryBuilder queryBuilder) {
            IndexCoordinates indexCoordinatesFor = elasticsearchRestTemplate.getIndexCoordinatesFor(entity.getClass());
            return elasticsearchRestTemplate.search(queryBuilder.build(), entity.getClass(), indexCoordinatesFor);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    5. 复杂查询

    这里先介绍三个query
    TermQueryBuilder 精确匹配,MatchPhraseQueryBuilder 模糊匹配,BoolQueryBuilder布尔查询,布尔查询可以嵌套 前边两个条件

    // 精确匹配,对中文不友好(仅一个字符),没有分词器概念,查询条件为一个字符时可以多重匹配,多个字符类似于mysql 的等于条件
    //TermQueryBuilder
    TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("username", "wangw");
    // 模糊匹配,存在分词器概念,可将查询条件分成多个字符进行查询
    //MatchPhraseQueryBuilder
    MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("realname", "张");
    
    // 布尔查询,可以将上述的各种条件添加入bool中作为多条件查询
    BoolQueryBuilder
    
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    // 必须条件 and
    boolQueryBuilder.must(termQueryBuilder);
    // 只要满足即可 or
    boolQueryBuilder.should(termQueryBuilder);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这里贴一个查询实例:

     public void test() {
    	MatchPhraseQueryBuilder termQueryBuilder = QueryBuilders.matchPhraseQuery("nickname", "可恶");
        MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("realname", "张");
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(termQueryBuilder);
        boolQueryBuilder.should(termQueryBuilder);
    // 查询条件
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withSourceFilter(new FetchSourceFilterBuilder().build())
                // 高亮
                .withHighlightFields(
                        new HighlightBuilder.Field("nickname"),
                        new HighlightBuilder.Field("realname")
                )
                // 去除查询结果 只取聚合查询的结果
                // 分页
                .withFields()
                .withPageable(PageRequest.of(0, 10));
    IndexCoordinates indexCoordinatesFor = elasticsearchRestTemplate.getIndexCoordinatesFor(MyUser.class);
    SearchHits<MyUser> search = elasticsearchRestTemplate.search(queryBuilder.build(), MyUser.class, indexCoordinatesFor);
    
        List<SearchHit<MyUser>> searchHits = search.getSearchHits();
        List<MyUser> posts = new ArrayList<>();
        //遍历返回的内容进行处理
        for(SearchHit<MyUser> searchHit:searchHits){
            //高亮的内容
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            //将高亮的内容填充到content中
            searchHit.getContent().setNickname(highlightFields.get("nickname")==null ? searchHit.getContent().getNickname():highlightFields.get("nickname").get(0));
            searchHit.getContent().setRealname(highlightFields.get("realname")==null ? searchHit.getContent().getRealname():highlightFields.get("realname").get(0));
            //放到实体类中
            posts.add(searchHit.getContent());
        }
        System.out.println(posts);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    多地如何组网?如何异地组网?
    责任链模式
    解决svn update 产生Node remains in conflict的报错问题
    Opencv3.4版本+ffmpeg联合编译
    《虹口区促进元宇宙产业发展的试行办法》的通知
    图片怎么压缩到100k以下?
    一键生成 API 文档的妙招
    Windows安装Redis及简单使用
    【HTML5入门指北】第二篇 网页相关的标签
    第六章:java ==与equals
  • 原文地址:https://blog.csdn.net/gd898989/article/details/126487832