美文网首页
Elasticsearch springboot整合ES

Elasticsearch springboot整合ES

作者: dylan丶QAQ | 来源:发表于2020-10-23 15:29 被阅读0次

    起因:在项目开发过程中,要使用到搜索 引擎来对一些关键字实现逆向查询,如果仅用模糊搜索,那么搜索的时间会根据数据量的增大而增大,对比之下就学了elasticsearch,也记录一下,常常回顾。


    1. Springboot整合Elasticsearch进行索引操作

    POM中增加依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    

    yaml配置

    # 端口一定要9300
    spring:
      data:
        elasticsearch:
          cluster-name: icoding-es
          cluster-nodes: 47.92.163.109:9300
    

    创建映射的po

    package com.icodingedu.po;
    
    import lombok.Data;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.elasticsearch.annotations.Document;
    import org.springframework.data.elasticsearch.annotations.Field;
    
    //indexName相当于给索引明名
    //type相当于文档类型
    @Data
    @Document(indexName = "index_user",type = "_doc",shards = 3,replicas = 1)
    public class UserBo {
        //index的doc的id和数据的id一致
        @Id
        private String id;
    
        //默认不是存储节点,要声明
        @Field(store = true,index = true,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
        private String nickname;
    
        @Field(store = true)
        private Integer sex;
    
        @Field(store = true)
        private Double consume;
    
        @Field(store = true,index = true,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
        private String review;
    }
    

    创建索引的controller

    package com.icodingedu.controller;
    
    import com.icodingedu.po.UserBo;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
    import org.springframework.data.elasticsearch.core.query.IndexQuery;
    import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    public class ESUserController {
    
        @Autowired
        ElasticsearchTemplate elasticsearchTemplate;
    
        @GetMapping("/create_index")
        @ResponseBody
        public String createIndex(){
            UserBo userBo = new UserBo();
            userBo.setId("1001");
            userBo.setConsume(1899.66);
            userBo.setNickname("空中雄鹰");
            userBo.setReview("icoding edu 艾编程课程非常不错,学起来很给力");
            userBo.setSex(1);
    
            IndexQuery indexQuery = new IndexQueryBuilder()
                    .withObject(userBo)
                    .build();
            elasticsearchTemplate.index(indexQuery);
            return "index/mapping/document 一起创建完成";
        }
    }
    

    更新索引的mapping

    // 只需要在po里加上字段既可以
    // 创建的时候给赋值
    // 更新的时候elasticsearchTemplate会根据po的变化判断是否更新
    // 在elasticsearchTemplate.index(indexQuery)操作时如果没有index则新建,如果有就创建数据
    

    删除index

    @GetMapping("/delete-index")
    @ResponseBody
    public String deleteIndex(){
      elasticsearchTemplate.deleteIndex(UserBo.class);
      return "删除成功";
    }
    

    ElasticsearchTemplate一般用于对文档数据进行检索应用

    • 对于index的mapping还是使用json来创建
    • ET的部分注解不一定生效

    2. Springboot对ES文档进行操作

    更新document

        @GetMapping("/update")
        @ResponseBody
        public String updateIndex(){
    
            Map<String,Object> data = new HashMap<String,Object>();
            data.put("username","jackwang");
            data.put("consume",7888.99);
    
            IndexRequest indexRequest = new IndexRequest();
            indexRequest.source(data);
    
            UpdateQuery updateQuery = new UpdateQueryBuilder()
                    .withClass(UserBo.class)
                    .withId("1001")
                    .withIndexRequest(indexRequest)
                    .build();
    
            elasticsearchTemplate.update(updateQuery);
            return "更新成功";
        }
    

    删除document

        @GetMapping("/delete/{id}")
        @ResponseBody
        public String deleteDocument(@PathVariable("id") String uid){
            elasticsearchTemplate.delete(UserBo.class,uid);
            return "删除id:"+uid;
        }
    

    根据id获得doc数据

        @GetMapping("/get/{id}")
        @ResponseBody
        public String getIndex(@PathVariable("id") String uid){
    
            GetQuery query = new GetQuery();
            query.setId(uid);
    
            UserBo userBo = elasticsearchTemplate.queryForObject(query,UserBo.class);
            return userBo.toString();
        }
    

    3. Springboot对ES文档进行分页查询

    // ES中已有的index映射对象
    package com.icodingedu.po;
    
    import lombok.Data;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.elasticsearch.annotations.Document;
    import org.springframework.data.elasticsearch.annotations.Field;
    
    @Data
    @Document(indexName = "index_customer",type = "_doc")
    public class CustomerPo {
        @Id
        private String id;
    
        @Field(store=true)
        private Integer age;
    
        @Field(store=true)
        private String username;
    
        @Field(store=true)
        private String nickname;
        @Field(store=true)
        private Float consume;
    
        @Field(store=true)
        private String desc;
    
        @Field(store=true)
        private Integer sex;
    
        @Field(store=true)
        private String birthday;
    
        @Field(store=true)
        private String city;
    
        @Field(store=true)
        private String faceimg;
    }
    

    查询分页的controller

        @GetMapping("/list")
        @ResponseBody
        public String getList(){
            //3.定义分页
            Pageable pageable = PageRequest.of(0,2);
            //2.定义query对象
            SearchQuery query = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.matchQuery("desc","艾编程 学习"))
                    .withPageable(pageable)
                    .build();
            //1.先写查询
            AggregatedPage<CustomerPo> customerPos = elasticsearchTemplate.queryForPage(query,CustomerPo.class);
            System.out.println("总页数:"+customerPos.getTotalPages());
            System.out.println("总记录数:"+customerPos.getTotalElements());
            List<CustomerPo> customerPoList = customerPos.getContent();
            for (CustomerPo customerPo:customerPoList) {
                System.out.println(customerPo.toString());
    
            }
            return "查询完成";
        }
    

    4. Springboot对ES文档实现高亮查询

    //目前已加入高亮的字符,但会报错,无法获得值
        @GetMapping("/listhiglight")
        @ResponseBody
        public String getListHighLight(){
            //4.定义高亮的字符
            String preTag = "<font color='red'>";
            String postTag = "</font>";
            //3.定义分页
            Pageable pageable = PageRequest.of(0,2);
            //2.定义query对象
            SearchQuery query = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.matchQuery("desc","艾编程 学习"))
                    .withHighlightFields(new HighlightBuilder.Field("desc").preTags(preTag).postTags(postTag))
                    .withPageable(pageable)
                    .build();
            //1.先写查询,参数里增加高亮的实现
            AggregatedPage<CustomerPo> customerPos = elasticsearchTemplate.queryForPage(query, CustomerPo.class, new SearchResultMapper() {
                @Override
                public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                    return null;
                }
    
                @Override
                public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
                    return null;
                }
            });
            System.out.println("总页数:"+customerPos.getTotalPages());
            System.out.println("总记录数:"+customerPos.getTotalElements());
            List<CustomerPo> customerPoList = customerPos.getContent();
            for (CustomerPo customerPo:customerPoList) {
                System.out.println(customerPo.toString());
    
            }
            return "查询完成";
        }
    

    实现高亮完整代码

        @GetMapping("/listhiglight")
        @ResponseBody
        public String getListHighLight(){
            //4.定义高亮的字符
            String preTag = "<font color='red'>";
            String postTag = "</font>";
            //3.定义分页
            Pageable pageable = PageRequest.of(0,2);
            //2.定义query对象
            SearchQuery query = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.matchQuery("desc","艾编程 学习"))
                    .withHighlightFields(new HighlightBuilder.Field("desc").preTags(preTag).postTags(postTag))
                    .withPageable(pageable)
                    .build();
            //1.先写查询,参数里增加高亮的实现
            AggregatedPage<CustomerPo> customerPos = elasticsearchTemplate.queryForPage(query, CustomerPo.class, new SearchResultMapper() {
                @Override
                public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                    List<CustomerPo> customerPoList = new ArrayList<CustomerPo>();
                    SearchHits searchHits = searchResponse.getHits();
                    for (SearchHit h: searchHits) {
                        HighlightField highlightField = h.getHighlightFields().get("desc");
                        String desc = highlightField.fragments()[0].toString();
                        CustomerPo customerPoHighlight = new CustomerPo();
                        customerPoHighlight.setAge((Integer)h.getSourceAsMap().get("age"));
                        customerPoHighlight.setBirthday(h.getSourceAsMap().get("birthday").toString());
                        customerPoHighlight.setCity(h.getSourceAsMap().get("city").toString());
                        customerPoHighlight.setConsume(Float.valueOf(h.getSourceAsMap().get("consume").toString()));
                        customerPoHighlight.setDesc(desc);//这就是把高亮的字段替换给原字段
                        customerPoHighlight.setFaceimg(h.getSourceAsMap().get("faceimg").toString());
                        customerPoHighlight.setId(h.getSourceAsMap().get("id").toString());
                        customerPoHighlight.setNickname(h.getSourceAsMap().get("nickname").toString());
                        customerPoHighlight.setSex((Integer)h.getSourceAsMap().get("sex"));
                        customerPoHighlight.setUsername(h.getSourceAsMap().get("username").toString());
                        customerPoList.add(customerPoHighlight);
                    }
                    if(customerPoList.size()>0){
                        return new AggregatedPageImpl<>((List<T>) customerPoList);
                    }
                    return null;
                }
    
                @Override
                public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
                    return null;
                }
            });
            System.out.println("总页数:"+customerPos.getTotalPages());
            System.out.println("总记录数:"+customerPos.getTotalElements());
            List<CustomerPo> customerPoList = customerPos.getContent();
            for (CustomerPo customerPo:customerPoList) {
                System.out.println(customerPo.toString());
    
            }
            return "查询完成";
        }
    

    5. Springboot对ES文档进行数据排序

    只需要加入排序的构建就ok了

        @GetMapping("/list")
        @ResponseBody
        public String getList(){
            //4.加入排序构建
            SortBuilder sortBuilder1 = new FieldSortBuilder("consume")
                    .order(SortOrder.DESC);
            SortBuilder sortBuilder2 = new FieldSortBuilder("age")
                    .order(SortOrder.ASC);
    
            //3.定义分页
            Pageable pageable = PageRequest.of(0,6);
            //2.定义query对象
            SearchQuery query = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.matchQuery("desc","学习"))
                    .withPageable(pageable)
                    .withSort(sortBuilder1)
                    .withSort(sortBuilder2)
                    .build();
            //1.先写查询
            AggregatedPage<CustomerPo> customerPos = elasticsearchTemplate.queryForPage(query,CustomerPo.class);
            System.out.println("总页数:"+customerPos.getTotalPages());
            System.out.println("总记录数:"+customerPos.getTotalElements());
            List<CustomerPo> customerPoList = customerPos.getContent();
            for (CustomerPo customerPo:customerPoList) {
                System.out.println(customerPo.toString());
    
            }
            return "查询完成";
        }
    

    不要以为每天把功能完成了就行了,这种思想是要不得的,互勉~!

    相关文章

      网友评论

          本文标题:Elasticsearch springboot整合ES

          本文链接:https://www.haomeiwen.com/subject/icbwpktx.html