springboot2.2.5.RELEASE整合springDataElasticsearch Elasticsearch7.6.x 版本

Posted 雨听风说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot2.2.5.RELEASE整合springDataElasticsearch Elasticsearch7.6.x 版本相关的知识,希望对你有一定的参考价值。

本文使用内容    springBoot2.2.5.RELEASE版本   Elasticsearch7.6.2  linux版本的   SpringDataElasticSearch与Springboot版本对应

一、操作准备

1、导入依赖

此处版本

2.2.5.RELEASE
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

2、创建application.yml文件

spring:
  elasticsearch:
    rest:
      uris: http://192.168.0.211:9200

此处的ip:端口  是自己的Elasticsearch的,如果为集群可以以逗号(,)隔开

3、创建实体类对象

 1 package cn.cqsw.elasticsearch.pojo;
 2 
 3 import org.springframework.data.annotation.Id;
 4 import org.springframework.data.elasticsearch.annotations.Document;
 5 import org.springframework.data.elasticsearch.annotations.Field;
 6 import org.springframework.data.elasticsearch.annotations.FieldType;
 7 
 8 import java.io.Serializable;
 9 
10 @Document(indexName = "item" , type = "_doc",shards = 1,replicas = 0)
11 public class Item implements Serializable {
12     @Id    //注意此处的@Id必须为springframework包下面的id   import org.springframework.data.annotation.Id;
13     Long id;
14     @Field(type = FieldType.Text,analyzer = "ik_max_word")
15     String title; //标题
16     @Field(type = FieldType.Keyword)
17     String category;// 分类
18     @Field(type = FieldType.Keyword)
19     String brand; // 品牌
20     @Field(type = FieldType.Double)
21     Double price; // 价格
22     @Field(type = FieldType.Keyword,index = false)
23     String images; // 图片地址
24 
25     public Long getId() {
26         return id;
27     }
28 
29     public void setId(Long id) {
30         this.id = id;
31     }
32 
33     public String getTitle() {
34         return title;
35     }
36 
37     public void setTitle(String title) {
38         this.title = title;
39     }
40 
41     public String getCategory() {
42         return category;
43     }
44 
45     public void setCategory(String category) {
46         this.category = category;
47     }
48 
49     public String getBrand() {
50         return brand;
51     }
52 
53     public void setBrand(String brand) {
54         this.brand = brand;
55     }
56 
57     public Double getPrice() {
58         return price;
59     }
60 
61     public void setPrice(Double price) {
62         this.price = price;
63     }
64 
65     public String getImages() {
66         return images;
67     }
68 
69     public void setImages(String images) {
70         this.images = images;
71     }
72 
73     public Item() {
74     }
75 
76     public Item(Long id, String title, String category, String brand, Double price, String images) {
77         this.id = id;
78         this.title = title;
79         this.category = category;
80         this.brand = brand;
81         this.price = price;
82         this.images = images;
83     }
84 
85 
86     @Override
87     public String toString() {
88         return "Item{" +
89                 "id=" + id +
90                 ", title=\'" + title + \'\\\'\' +
91                 ", category=\'" + category + \'\\\'\' +
92                 ", brand=\'" + brand + \'\\\'\' +
93                 ", price=" + price +
94                 ", images=\'" + images + \'\\\'\' +
95                 \'}\';
96     }
View Code

注解参数含义解释

Spring Data通过注解来声明字段的映射属性,有下面的三个注解:

- `@Document` 作用在类,标记实体类为文档对象,一般有四个属性
  - indexName:对应索引库名称
  - type:对应在索引库中的类型   在ElasticSearch7.x中取消了type的概念
  - shards:分片数量,默认5
  - replicas:副本数量,默认1
- `@Id` 作用在成员变量,标记一个字段作为id主键
- `@Field` 作用在成员变量,标记为文档的字段,并指定字段映射属性:
  - type:字段类型,取值是枚举:FieldType
  - index:是否索引,布尔类型,默认是true
  - store:是否存储,布尔类型,默认是false
  - analyzer:分词器名称:ik_max_word    ik分词器内容,看另外一个随笔:https://www.cnblogs.com/TJ21/p/12642242.html

4、创建一个空的Repository的接口  

不明白为什么可以看一些Spring-Data文档

5、创建启动类

@SpringBootApplication
public class ElasticSearchApplication {

    public static void main(String[] args) {
        SpringApplication.run(ElasticSearchApplication.class);
    }
}

6、创建测试

 

 测试   

注意

此处使用  

ElasticsearchRestTemplate   模板原因为 :  ElasticsearchTemplate 模板使用的是使用的 TransportClient 此客户端在ElasticSearch7的版本中不再推荐使用,
在8的版本中将被移除,官方建议使用:High Level REST Client (高级Test客户端)
不使用ElasticsearchTemplate
原因查看官方文档:https://docs.spring.io/spring-data/elasticsearch/docs/3.2.6.RELEASE/reference/html/#elasticsearch.clients.transport

 

使用ElasticsearchRestTemplate   原因:官方文档:https://docs.spring.io/spring-data/elasticsearch/docs/3.2.6.RELEASE/reference/html/#elasticsearch.operations.resttemplate

这样我们使用的就是: High Level REST Client (高级Test客户端)

 

 

使用junit4

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class ElasticisesTest {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ItemRepository itemRepository;


    @Test
    public void addIndexTest() {
        this.elasticsearchRestTemplate.createIndex(Item.class);
        this.elasticsearchRestTemplate.putMapping(Item.class);
    }


    @Test
    public void deleteIndex() {
        this.elasticsearchRestTemplate.deleteIndex("item");
    }

    /**
     * 新增和批量新增
     */
    @Test
    public void create() {

        /*新增*/
//        Item item = new Item(1L, "小米手机7", " 手机", "小米", 3499.00, "http://image.leyou.com/13123.jpg");
//        this.itemRepository.save(item);

        List<Item> list = new ArrayList<>();
        list.add(new Item(2L, "坚果手机R1", " 手机", "锤子", 3699.00, "http://image.leyou.com/123.jpg"));
        list.add(new Item(3L, "华为META10", " 手机", "华为", 4499.00, "http://image.leyou.com/3.jpg"));
        // 接收对象集合,实现批量新增
        this.itemRepository.saveAll(list);
    }


    /**
     * 查询全部
     */
    @Test
    public void find() {
        Optional<Item> item = this.itemRepository.findById(1L);
        System.out.println("item.get() = " + item.get());
    }


    /**
     * 查询并排序
     */
    @Test
    public void findAllSort() {
        Iterable<Item> items = this.itemRepository.findAll(Sort.by("price").descending());

        items.forEach(System.out::println);
    }


    /**
     * 根据title查询
     */
    @Test
    public void findByTitle() {
        Iterable<Item> items = this.itemRepository.findByTitle("手机");
        items.forEach(System.out::println);
    }


    /**
     * 查询价格区间
     */
    @Test
    public void findByPrice() {
        List<Item> byPriceBetween = this.itemRepository.findByPriceBetween(3699d, 4499d);
        byPriceBetween.forEach(System.out::println);
    }


    /**
     * 添加测试数据
     */
    @Test
    public void indexList() {
        List<Item> list = new ArrayList<>();
        list.add(new Item(1L, "小米手机7", "手机", "小米", 3299.00, "http://image.leyou.com/13123.jpg"));
        list.add(new Item(2L, "坚果手机R1", "手机", "锤子", 3699.00, "http://image.leyou.com/13123.jpg"));
        list.add(new Item(3L, "华为META10", "手机", "华为", 4499.00, "http://image.leyou.com/13123.jpg"));
        list.add(new Item(4L, "小米Mix2S", "手机", "小米", 4299.00, "http://image.leyou.com/13123.jpg"));
        list.add(new Item(5L, "荣耀V10", "手机", "华为", 2799.00, "http://image.leyou.com/13123.jpg"));
        // 接收对象集合,实现批量新增
        itemRepository.saveAll(list);
    }

    /**
     * 通过标题查询
     */
    @Test
    public void testSearch() {
        // 通过查询构建器构建查询条件
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "手机");
        //执行查询
        Iterable<Item> items = this.itemRepository.search(matchQueryBuilder);
        items.forEach(System.out::println);
    }

    @Test
    public void testNative() {
        //构建自定义查询构建器
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        //添加基本的查询条件
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "手机");
        //执行查询获取分页结果集
        nativeSearchQueryBuilder.withQuery(matchQueryBuilder);

        Page<Item> items = this.itemRepository.search(nativeSearchQueryBuilder.build());
        System.out.println("items.getTotalElements() = " + items.getTotalElements());
        System.out.println("items.getTotalPages() = " + items.getTotalPages());
        items.forEach(System.out::println);

    }


    /**
     * 分页查询
     */

    @Test
    public void testNativeQuery() {
        // 构建查询条件
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        // 添加基本的分词查询
        queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));

        // 初始化分页参数
        int page = 0;
        int size = 3;
        // 设置分页参数
        queryBuilder.withPageable(PageRequest.of(page, size));

        // 执行搜索,获取结果
        Page<Item> items = this.itemRepository.search(queryBuilder.build());
        // 打印总条数
        System.out.println(items.getTotalElements());
        // 打印总页数
        System.out.println(items.getTotalPages());
        // 每页大小
        System.out.println(items.getSize());
        // 当前页
        System.out.println(items.getNumber());
        items.forEach(System.out::println);
    }

    @Test
    public void testAggs() {

        //初始化自定义构建查询器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        //添加聚合
        queryBuilder.addAggregation(AggregationBuilders.terms("brandAgg").field("brand"));

        //添加结果集过滤不包括任何字段
        queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{}, null));

        //执行查询
        AggregatedPage<Item> itemPage = (AggregatedPage<Item>)this.itemRepository.search(queryBuilder.build());


        /*
        解析聚合结果集,根据聚合的类型以及字段类型,要进行强转,不然无法获取桶
         brand-是字符串类型的,聚合类型是词条类型的
        brandAgg-通过聚合名称获取聚合对象
        使用StringTerms强转的时候出现错误
         */

        ParsedStringTerms brandAgg =(ParsedStringTerms) itemPage.getAggregation("brandAgg");

        //获取桶
        List<? extends Terms.Bucket> buckets = brandAgg.getBuckets();

        //遍历输出
        buckets.forEach(bucket -> {
            System.out.println("bucket.getKeyAsString() = " + bucket.getKeyAsString());
            //获取条数
            System.out.println("bucket.getDocCount() = " + bucket.getDocCount());
        });

    }


    /**
     * 子聚合
     */
    @Test
    public void testSubAggs() {

        //初始化自定义构建查询器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        //添加聚合
        queryBuilder.addAggregation(AggregationBuilders.terms("brandAgg").field("brand").subAggregation(AggregationBuilders.avg("price_avg").field("price")));

        //添加结果集过滤不包括任何字段
        queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{}, null));

        //执行查询
        AggregatedPage<Item> itemPage = (AggregatedPage<Item>)this.itemRepository.search(queryBuilder.build());


        /*
        解析聚合结果集,根据聚合的类型以及字段类型,要进行强转,不然无法获取桶
         brand-是字符串类型的,聚合类型是词条类型的
        brandAgg-通过聚合名称获取聚合对象
        使用StringTerms强转的时候出现错误
         */

        StringTerms brandAgg =(StringTerms) itemPage.getAggregation("brandAgg");

        //获取桶
        List<StringTerms.Bucket> buckets = brandAgg.getBuckets();

        //遍历输出
        buckets.forEach(bucket -> {
            System.out.println("bucket.getKeyAsString() = " + bucket.getKeyAsString());
            //获取条数
            System.out.println("bucket.getDocCount() = " + bucket.getDocCount());
            
            //获取子聚合的map集合:key-聚合名称,value-对应的子聚合对象
            Map<String, Aggregation> stringAggregationMap = bucket.getAggregations().asMap();
            /*
            以前使用的InternalAvg强转出现转换异常
             */
            ParsedAvg price_avg =(ParsedAvg) stringAggregationMap.get("price_avg");


            System.out.println("price_avg.getValue() = " + price_avg.getValue());
        });

    }

}

 

以上是关于springboot2.2.5.RELEASE整合springDataElasticsearch Elasticsearch7.6.x 版本的主要内容,如果未能解决你的问题,请参考以下文章

使用docker容器的错误时间戳:时区设置无效

Java使用elasticsearch基础API使用(配置+API测试源码)

SSM框架整合—详细整合教程(Spring+SpringMVC+MyBatis)

SSM框架整合—详细整合教程(Spring+SpringMVC+MyBatis)

SpringBoot系列八:SpringBoot整合消息服务(SpringBoot 整合 ActiveMQSpringBoot 整合 RabbitMQSpringBoot 整合 Kafka)

SpringBoot——整合SSM(主要整合MyBatis)