• SpringBoot整合ElasticSearch


    7 SpringBoot整合ElasticSearch

    7.1 导入依赖
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-elasticsearchartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    7.2 写yml
    spring:
      elasticsearch:
        rest:
          uris: 127.0.0.1:9200 #地址
    
    • 1
    • 2
    • 3
    • 4
    7.3 实体映射
    package com.cxs.elasticsearch.entity;
    
    import lombok.Data;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.elasticsearch.annotations.DateFormat;
    import org.springframework.data.elasticsearch.annotations.Document;
    import org.springframework.data.elasticsearch.annotations.Field;
    import org.springframework.data.elasticsearch.annotations.FieldType;
    
    import java.time.LocalDateTime;
    
    /*
     * @Author:cxs
     * @Motto:放下杂念,只为迎接明天更好的自己
     * */
    @Data
    @Document(indexName = "good_item_index")
    public class GoodItem {
        @Id
        private Long id;
        @Field(type = FieldType.Long)
        private Long spu;
        @Field(type = FieldType.Long)
        private Long sku;
        @Field(type = FieldType.Text)
        private String title;
        @Field(type = FieldType.Long)
        private Long price;
        @Field(type = FieldType.Text)
        private String pic;
        @Field(type = FieldType.Text)
        private String url;
        @Field(type = FieldType.Date, format = DateFormat.date)
        private LocalDateTime createTime;
        @Field(type = FieldType.Date, format = DateFormat.date)
        private LocalDateTime updateTime;
    }
    
    • 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
    7.4 Dao
    package com.cxs.elasticsearch.dao;
    
    import com.cxs.elasticsearch.entity.GoodItem;
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    import org.springframework.stereotype.Repository;
    
    /*
     * @Author:cxs
     * @Motto:放下杂念,只为迎接明天更好的自己
     * */
    @Repository
    public interface GoodItenDao extends ElasticsearchRepository<GoodItem, Long> {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    7.5 Service
    package com.cxs.service.impl;
    
    import com.cxs.elasticsearch.dao.GoodItenDao;
    import com.cxs.elasticsearch.entity.GoodItem;
    import com.cxs.service.GoodService;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
    import org.springframework.stereotype.Service;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    /*
     * @Author:cxs
     * @Motto:放下杂念,只为迎接明天更好的自己
     * */
    @Service
    public class GoodServiceImpl implements GoodService {
        @Autowired
        private GoodItenDao goodItenDao;
    
        @Autowired
        private ElasticsearchRestTemplate elasticsearchRestTemplate;
    
        @Override
        public Boolean save(GoodItem goodItem) {
            GoodItem save = goodItenDao.save(goodItem);
            System.out.println(save);
            return save != null;
        }
    
        @Override
        public List<GoodItem> findAll() {
            Iterable<GoodItem> all = goodItenDao.findAll();
            List<GoodItem> list = new ArrayList<>();
               all.forEach(a -> {
                   list.add(a);
               });
            return list;
        }
    
        @Override
        public List<GoodItem> search(GoodItem goodItem) {
            Iterable<GoodItem> search = goodItenDao.search(QueryBuilders.termsQuery("url", goodItem.getUrl()));
            List<GoodItem> list = new ArrayList<>();
            search.forEach(a -> {
                list.add(a);
            });
            return list;
        }
    
        @Override
        public List<GoodItem> query(GoodItem goodItem) {
            List<GoodItem> list = new ArrayList<>();
            GoodItem item = elasticsearchRestTemplate.get("", GoodItem.class);
            return list;
        }
    }
    
    • 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
    7.6 测试
    //  ... 测试省略
    
    • 1
    7.7 复杂查询

    ElasticsearchRepository中许多方法已经被弃用,实现复杂操作就需要自己实现,注入

    ElasticsearchRestTemplate完成复杂操作,注意,原先的ElasticsearchTemplate已经弃用

    7.7.1 使用ElasticsearchRestTemplate完成Match查询
    // 匹配url is https://item.jd.com/100016034400.html
    MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("url", "https://item.jd.com/100016034400.html");
    NativeSearchQuery query = new NativeSearchQuery(matchQueryBuilder);
    SearchHits<GoodItem> search = elasticsearchRestTemplate.search(query, GoodItem.class);
    List<SearchHit<GoodItem>> hits = search.getSearchHits();
    List<GoodItem> list = new ArrayList<>();
    // 总数
    long totalHits = search.getTotalHits();
    for (SearchHit<GoodItem> hit : hits) {
        GoodItem content = hit.getContent();
        list.add(content);
    }
    System.out.println(list);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    7.7.2 使用ElasticsearchRestTemplate完成Bool查询
        @Test
        void contextLoads1() {
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("url", "https://item.jd.com/100016034400.html");
            TermQueryBuilder termQuery = QueryBuilders.termQuery("url", "https://item.jd.com/100016034400.html");
            boolQueryBuilder.should(matchQuery).should(termQuery);
            NativeSearchQuery query = new NativeSearchQuery(boolQueryBuilder);
            SearchHits<GoodItem> search = elasticsearchRestTemplate.search(query, GoodItem.class);
            System.out.println(search);
            List<SearchHit<GoodItem>> hits = search.getSearchHits();
            List<GoodItem> list = new ArrayList<>();
            long totalHits = search.getTotalHits();
            for (SearchHit<GoodItem> hit : hits) {
                GoodItem content = hit.getContent();
                list.add(content);
            }
            System.out.println(list);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    7.7.3 Es批量操作,存在即修改,不存在即插入
        @Test
        void contextLoads1() {
            BulkRequest bulkRequest = new BulkRequest();
            for (FinancialDoc document : documents) {
                document.setProdId(getProductId(document));
                document.setRefreshTime(LocalDateTime.now());
                IndexRequest indexRequest = new IndexRequest(getIndex())
                        .id(document.getProdId())
                        .source(JSON.toJSONString(document), XContentType.JSON);
                UpdateRequest request = new UpdateRequest(getIndex(), document.getProdId())
                        .doc(JSON.toJSONString(document), XContentType.JSON).upsert(indexRequest);
                bulkRequest.add(request);
            }
            BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
            return bulkResponse.status().equals(RestStatus.OK);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    7.7.4 Es全量查询文档,总数大于10000条

    使用scroll,每次1000条查询,可自行调整

    public List<StockDoc> selectAllList() throws IOException {
            SearchRequest request = new SearchRequest();
            request.indices(getIndex());
            List<StockDoc> result = new ArrayList<>();
            SearchSourceBuilder builder = new SearchSourceBuilder();
            builder.size(1000).query(QueryBuilders.matchAllQuery());
            Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L));
            request.scroll(scroll)
                    .source(builder);
            SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);
            String scrollId = searchResponse.getScrollId();
            SearchHit[] searchHits = searchResponse.getHits().getHits();
            while (searchHits != null && searchHits.length > 0) {
                SearchHits hits = searchResponse.getHits();
                for (SearchHit hit : hits) {
                    result.add(JSON.parseObject(hit.getSourceAsString(), StockDoc.class));
                }
                SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
                scrollRequest.scroll(scroll);
                searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
                searchHits = searchResponse.getHits().getHits();
            }
            ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
            clearScrollRequest.addScrollId(scrollId);
            client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
            return result;
        }
    
    • 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
    7.7.5 复杂搜索-权重,优先级排序
    private void globalSearchConditionHandler(SearchDTO dto, SearchSourceBuilder builder) {
            // 封装分页数据
            builder.from((dto.getPageNum() - 1) * dto.getPageSize());
            builder.size(dto.getPageSize());
            Script script =
                    new Script("if (doc['code.keyword'].value == '" + dto.getKeyword() + "') {return doc['code.keyword'].value.length();} else {if(doc['codeType.keyword'].value == '4353' || doc['codeType.keyword'].value == '4609') {return 1;} else {return 0;}}");
            Script codeTypeScript =
                    new Script("return Integer.parseInt(doc['codeType.keyword'].value)");
            SortBuilder sortBuilder = SortBuilders.scriptSort(script, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.DESC);
            SortBuilder codeTypeScriptBuild = SortBuilders.scriptSort(codeTypeScript, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.ASC);
            SortBuilder scoreBuild = SortBuilders.fieldSort("_score").order(SortOrder.DESC);
            SortBuilder codeBuild = SortBuilders.fieldSort("code.keyword").order(SortOrder.ASC);
            builder.sort(scoreBuild);
            builder.sort(sortBuilder);
            builder.sort(codeTypeScriptBuild);
            builder.sort(codeBuild);
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            if (StringUtils.hasLength(dto.getKeyword())) {
                BoolQueryBuilder query = QueryBuilders.boolQuery();
                query.should(QueryBuilders.wildcardQuery("code.keyword", swapLeftKey(dto.getKeyword())).boost(100.0f))
                        .should(QueryBuilders.wildcardQuery("code.keyword", swapKey(dto.getKeyword())).boost(90.0f))
                        .should(QueryBuilders.wildcardQuery("codeName.keyword", swapLeftKey(dto.getKeyword())).boost(10.0f))
                        .should(QueryBuilders.wildcardQuery("codeName.keyword", swapKey(dto.getKeyword())).boost(9.5f))
                        .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapLeftKey(dto.getKeyword())).boost(9.0f))
                        .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapLeftKey(dto.getKeyword().toUpperCase(Locale.ROOT))).boost(9.0f))
                        .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapLeftKey(dto.getKeyword().toUpperCase(Locale.ROOT))).boost(9.0f))
                        .should(QueryBuilders.regexpQuery("pinYin.keyword", regexStr(dto.getKeyword().toUpperCase(Locale.ROOT))).boost(8.0f))
                        .should(QueryBuilders.regexpQuery("pinYin.keyword", regexStr(dto.getKeyword().toLowerCase(Locale.ROOT))).boost(8.0f))
                        .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapKey(dto.getKeyword())).boost(7.0f))
                        .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapKey(dto.getKeyword().toUpperCase(Locale.ROOT))).boost(7.0f))
                        .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapKey(dto.getKeyword().toLowerCase(Locale.ROOT))).boost(7.0f));
                boolQuery.must(query);
            }
            builder.query(boolQuery);
        }
    
    • 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

  • 相关阅读:
    RabbitMQ学习笔记
    你可能不太了解的前端知识
    IT冷知识--每日一练
    8、python中的模块和包
    [Windows内核源码分析0] 引导过程(Phase0部分分析)
    了解JVM的相关概述,发现很多全忘了(文末福利)
    NVR监测软件/设备EasyNVR多品牌NVR管理工具/设备对城市安全有哪些具体益处?
    什么是DOM和DOM操作
    一周快速入门Python之day01
    15-55V输入自动升降压 光伏MPPT自动跟踪充电方案 大功率300瓦
  • 原文地址:https://blog.csdn.net/admin_2022/article/details/136267829