zoukankan      html  css  js  c++  java
  • 【Spring Boot】Spring Boot之使用 Spring Data Elasticsearch 整合elasticsearch

    一、Spring Data Elasticsearch简单介绍

      Spring Data Elasticsearch项目将核心Spring概念应用于使用Elasticsearch搜索引擎开发解决方案。我们提供了一个“模板”作为存储、查询、排序和划分文档的高级抽象。您将注意到Spring Framewor与Spring data solr和mongodb支持的相似之处

     GitHub地址:https://github.com/zhangboqing/spring-boot-demo-elasticsearch

     使用的spring boot版本:

    <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.2.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>

    二、整合步骤

    1)maven依赖

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

    2)application.yml

    spring:
      elasticsearch:
        rest:
          uris:
            - http://localhost:9200
          username: elastic
          password: 123456

    3)定义实体,一个实体对于一个index

    /**
     * @author zhangboqing
     * @date 2019-12-06
     */
    public interface EsConsts {
    
        /**
         * 所以index都使用该类型名称
         */
        String DEFAULT_TYPE_NAME = "_doc";
    
        /**
         * 索引名称
         */
        String INDEX_NAME_MERCURY = "goods";
    
    }
    /**
     * @author zhangboqing
     * @date 2019-12-06
     */
    @Document(indexName = EsConsts.INDEX_NAME_MERCURY, type = EsConsts.DEFAULT_TYPE_NAME, shards = 1, replicas = 0)
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class GoodsESEntity {
        // 筛选条件包括:商品名称,品牌,规格,适用车型,商品编号,原厂编号
    
        /**
         * 主键,商品ID
         */
        @Id
        private Long goodsId;
    
        /**
         * 商品名称
         */
        @Field(type = FieldType.Keyword)
        private String goodsName;
        /**
         * 品牌
         */
        @Field(type = FieldType.Keyword)
        private String goodBrand;
        /**
         * 规格
         */
        @Field(type = FieldType.Keyword)
        private String goodsSpec;
        /**
         * 商品编号
         */
        @Field(type = FieldType.Keyword)
        private String goodsAccessoriesCode;
        /**
         * 原厂编号
         */
        @Field(type = FieldType.Keyword)
        private String goodsOriginalFactoryCode;
    
        /**
         * 复合字段,会被分词后存储
         */
        @Field(type = FieldType.Text, analyzer = "ik_smart")
        private String groupData;
    }

    4)定义Repository

    /**
     * @author zhangboqing
     * @date 2019-12-06
     */
    public interface GoodsESRepository extends ElasticsearchRepository<GoodsESEntity, Long> {
    
        /**
         * 根据goodsId区间查询
         */
        List<GoodsESEntity> findByGoodsIdBetween(Integer min, Integer max);
    
    }

    三、测试

    /**
     * @Author zhangboqing
     * @Date 2020-01-03
     */
    @SpringBootTest
    @Slf4j
    public class GoodsESRepositoryTest {
    
        @Autowired
        private GoodsESRepository goodsESRepository;
    
        /**
         * 测试新增
         */
        @Test
        public void save() {
            GoodsESEntity goodsESEntity1 = new GoodsESEntity(2L, "尾灯 L 大众速腾", "国际品牌", "16D 945 095", "31231231", "16D 945 095",
                    "尾灯 L 大众速腾 国际品牌 16D 945 095 31231231 16D 945 095");
            GoodsESEntity goodsESEntity2 = new GoodsESEntity(1L, "", "国际品牌", "16D 945 095", "31231231", "16D 945 095",
                    "后 国际品牌 16D 945 095 31231231 16D 945 095");
            Iterable<GoodsESEntity> goodsESEntities = goodsESRepository.saveAll(Arrays.asList(goodsESEntity1, goodsESEntity2));
            log.info("【save】= {}", goodsESEntities);
        }
    
    
        /**
         * 测试更新
         */
        @Test
        public void update() {
            goodsESRepository.findById(1L).ifPresent(goodsESEntity -> {
                goodsESEntity.setGoodsName(goodsESEntity.getGoodsName() + "
    更新更新更新更新更新");
                GoodsESEntity save = goodsESRepository.save(goodsESEntity);
                log.info("【save】= {}", save);
            });
        }
    
        /**
         * 测试删除
         */
        @Test
        public void delete() {
            // 主键删除
            goodsESRepository.deleteById(1L);
    
            // 对象删除
            goodsESRepository.findById(2L).ifPresent(goodsESEntity -> goodsESRepository.delete(goodsESEntity));
    
            // 批量删除
            goodsESRepository.deleteAll(goodsESRepository.findAll());
        }
    
        /**
         * 测试普通查询,按goodsId倒序
         */
        @Test
        public void select() {
            goodsESRepository.findAll(Sort.by(Sort.Direction.DESC, "goodsId"))
                    .forEach(goodsESEntity -> log.info("【goods】: {}", JSON.toJSONString(goodsESEntity)));
        }
    
        /**
         * 自定义查询,根据goodsId范围查询
         */
        @Test
        public void customSelectRangeOfAge() {
            goodsESRepository.findByGoodsIdBetween(1, 2).forEach(goodsESEntity -> log.info("【goods】: {}", JSON.toJSONString(goodsESEntity)));
        }
    
        /**
         * 高级查询
         */
        @Test
        public void advanceSelect() {
            // QueryBuilders 提供了很多静态方法,可以实现大部分查询条件的封装
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("goodsName", "保时捷跑车V20");
            log.info("【queryBuilder】= {}", queryBuilder.toString());
    
            goodsESRepository.search(queryBuilder).forEach(goodsESEntity -> log.info("【goods】: {}", JSON.toJSONString(goodsESEntity)));
        }
    
        /**
         * 自定义高级查询
         */
        @Test
        public void customAdvanceSelect() {
            // 构造查询条件
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 添加基本的分词条件
            queryBuilder.withQuery(QueryBuilders.matchQuery("goodsName", "保时捷跑车V20"));
            // 排序条件
            queryBuilder.withSort(SortBuilders.fieldSort("goodsId").order(SortOrder.DESC));
            // 分页条件
            queryBuilder.withPageable(PageRequest.of(0, 2));
            Page<GoodsESEntity> goodsESEntities = goodsESRepository.search(queryBuilder.build());
            log.info("【people】总条数 = {}", goodsESEntities.getTotalElements());
            log.info("【people】总页数 = {}", goodsESEntities.getTotalPages());
            goodsESEntities.forEach(goodsESEntity -> log.info("【goods】= {}",JSON.toJSONString(goodsESEntity)));
        }
    
        /**
         * 测试聚合,测试平均goodsId
         */
        @Test
        public void avg() {
            // 构造查询条件
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 不查询任何结果
            queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    
            // 平均goodsId
            queryBuilder.addAggregation(AggregationBuilders.avg("goodsIdAvg").field("goodsId"));
    
            log.info("【queryBuilder】= {}", JSON.toJSONString(queryBuilder.build()));
    
            AggregatedPage<GoodsESEntity> goodsESEntities = (AggregatedPage<GoodsESEntity>) goodsESRepository.search(queryBuilder.build());
            double avgGoodsId = ((InternalAvg) goodsESEntities.getAggregation("goodsIdAvg")).getValue();
            log.info("【avgGoodsId】= {}", avgGoodsId);
        }
    
        /**
         * 测试高级聚合查询
         */
        @Test
        public void advanceAgg() {
            // 构造查询条件
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 不查询任何结果
            queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    
            // 1. 添加一个新的聚合,聚合类型为terms,聚合名称为goodsName,聚合字段为goodsId
            queryBuilder.addAggregation(AggregationBuilders.terms("goodsName").field("goodsName")
                    // 2. 在goodsName聚合桶内进行嵌套聚合,求平均goodsId
                    .subAggregation(AggregationBuilders.avg("goodsIdAvg").field("goodsId")));
    
            log.info("【queryBuilder】= {}", JSON.toJSONString(queryBuilder.build()));
    
            // 3. 查询
            AggregatedPage<GoodsESEntity> people = (AggregatedPage<GoodsESEntity>) goodsESRepository.search(queryBuilder.build());
    
            // 4. 解析
            // 4.1. 从结果中取出名为 goodsName 的那个聚合,因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
            StringTerms goodsName = (StringTerms) people.getAggregation("goodsName");
            // 4.2. 获取桶
            List<StringTerms.Bucket> buckets = goodsName.getBuckets();
            for (StringTerms.Bucket bucket : buckets) {
                // 4.3. 获取桶中的key,即goodsName名称  4.4. 获取桶中的文档数量
                log.info("{} 总共有 {} 个", bucket.getKeyAsString(), bucket.getDocCount());
                // 4.5. 获取子聚合结果:
                InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("goodsIdAvg");
                log.info("平均goodsId:{}", avg);
            }
        }
    
    }
  • 相关阅读:
    CAS 5.X 安装
    《从0到1》开启商业和未来的秘密
    阿里Java开发规约插件使用
    【Effective Java】阅读
    Java8 流的使用示例
    我对线程安全的理解
    APP微信支付实现
    如何将微信上传AMR格式语音转化为MP3格式
    如何在下载文件前确定文件名
    寻找水王1
  • 原文地址:https://www.cnblogs.com/756623607-zhang/p/12147410.html
Copyright © 2011-2022 走看看