Spring Data Elasticsearch-代碼版

Spring Data Elasticsearch-代碼版

項目結構

在這裏插入圖片描述

配置文件

  1. pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.leyou.demo</groupId>
        <artifactId>es-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>elasticsearch</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.2.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </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>
                <!-- 引入elasticSearch啓動器 -->
                <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>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <!-- maven插件 -->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
  2. application.yml

    spring:
      data:
        elasticsearch:
          cluster-name: elasticsearch  # 集羣名稱
          cluster-nodes: 192.168.79.128:9300  # 集羣地址
    

啓動類

  1. EsApplication

    package com.leyou;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * @program: es-demo
     * @description:
     * @author: Mr.Xiao
     * @create: 2020-06-10 09:59
     **/
    @SpringBootApplication
    public class EsApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EsApplication.class);
        }
    
    }
    
    

實體類

  1. Item

    package com.leyou.es.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.elasticsearch.annotations.Document;
    import org.springframework.data.elasticsearch.annotations.Field;
    import org.springframework.data.elasticsearch.annotations.FieldType;
    
    /**
     * @program: es-demo
     * @description:
     * @author: Mr.Xiao
     * @create: 2020-06-10 10:00
     **/
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    /*
        indexName: 索引庫名稱
        type: 類型
        shards: 分頁數量
        replicas: 副本數量
     */
    @Document(indexName = "xiaoge2", type = "item", shards = 1, replicas = 1)
    public class Item {
    
        @Field(type = FieldType.Long) // 聲明字段的類型
        @Id // 這個字段作爲索引庫的id來用
        Long id;
    
        /*
            指定爲text因爲標題將來要用來分詞
            analyzer: 指定分詞器
         */
        @Field(type = FieldType.Text, analyzer = "ik_smart")
        String title; //標題
    
        /*
            因爲商品分類是不需要分詞的, 所以用keyword
            index: 將來會用來當做搜索, 過濾, 默認爲true這裏可以不寫
         */
        @Field(type = FieldType.Keyword, index = true)
        String category;// 分類
    
        @Field(type = FieldType.Keyword, index = true)
        String brand; // 品牌
    
        @Field(type = FieldType.Double, index = true)
        Double price; // 價格
    
        /*
            因爲商品分類是不需要分詞的, 所以用keyword
            index: false 將來不能被搜索或者過濾
         */
        @Field(type = FieldType.Keyword, index = false)
        String images; // 圖片地址
    
    }
    
    

接口

  1. ItemRepository

    package com.leyou.es.repository;
    
    import com.leyou.es.pojo.Item;
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    
    import java.util.List;
    
    /**
     * @program: es-demo
     * @description: ElasticsearchRepository 第一個參數實體類類型, 第二個參數id類型
     * @author: Mr.Xiao
     * @create: 2020-06-10 15:35
     **/
    // ElasticsearchRepository 跟 通用mapper一樣, 裏面包含了各種增刪改查
    public interface ItemRepository extends ElasticsearchRepository<Item, Long> {
    
        /*
            自己寫一個範圍查詢的方法, 它會自動幫你實現, 比通用mapper更牛逼
            注意:
                當你寫方法名時: 它會有提示, 要有根據他提供的單詞意思來給方法取名, 不是瞎寫的
         */
        List<Item> findByPriceBetween(Double begin, Double end);
    
    }
    
    

測試

  1. EsTest

    package com.leyou.es.demo;
    
    import com.leyou.es.pojo.Item;
    import com.leyou.es.repository.ItemRepository;
    import org.elasticsearch.index.query.MatchQueryBuilder;
    import org.elasticsearch.index.query.QueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.search.aggregations.Aggregation;
    import org.elasticsearch.search.aggregations.AggregationBuilders;
    import org.elasticsearch.search.aggregations.Aggregations;
    import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
    import org.elasticsearch.search.sort.SortBuilders;
    import org.elasticsearch.search.sort.SortOrder;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
    import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
    import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
    import org.springframework.test.context.TestPropertySource;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.io.PrintStream;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @program: es-demo
     * @description:
     * @author: Mr.Xiao
     * @create: 2020-06-10 15:08
     **/
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class EsTest {
    
        @Autowired
        ElasticsearchTemplate template;  // 註冊ElasticsearchTemplate對象
    
        @Autowired
        private ItemRepository repository; // 註冊ItemRepository
    
        @Test
        public void testCreate() {
            // 創建索引庫
            template.createIndex(Item.class);
            // 創建映射關係
            template.putMapping(Item.class);
    
            /*
                刪除索引
                template.deleteIndex(Item.class);
             */
    
        }
    
        /**
         * find開頭的方法是查詢
         * save開頭的是新增, 如果id相同就是修改
         * delete開頭的是刪除
         */
        @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"));
            // 接收對象集合,實現批量新增
            repository.saveAll(list);
        }
    
        @Test
        public void testFind() {
            // 查詢所有
            Iterable<Item> items = repository.findAll();
            for (Item item : items) {
                System.out.println(item);
            }
        }
    
        @Test
        public void testFindPriceFilterBetween() {
            // 查詢價錢在2000-4000的商品
            Iterable<Item> items = repository.findByPriceBetween(2000d, 4000d);
            for (Item item : items) {
                System.out.println(item);
            }
        }
    
        /**
         * 基本查詢: 分詞查詢
         */
        @Test
        public void testQuery(){
            // QueryBuilders原生包下的, 構建條件
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "小米");
            // 執行查詢, 分詞查詢title中代用小米連個字的, 對象
            Iterable<Item> items = repository.search(queryBuilder);
            items.forEach(System.out::println);
        }
    
        /**
         * 自定義查詢
         */
        @Test
        public void testNativeQuery(){
            // 創建查詢構建器 spring提供的
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 結果過濾 FetchSourceFilter的兩個參數 includes excludes 效果就是elasticSearch中結果過濾的includes excludes
            queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{"id", "title", "price"}, null));
            // 添加基本的分詞查詢
            queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米"));
            // 執行搜索,獲取結果
            Page<Item> items = repository.search(queryBuilder.build());
            // 打印總條數
            System.out.println(items.getTotalElements());
            // 打印總頁數
            System.out.println(items.getTotalPages());
    
            items.forEach(System.out::println);
        }
    
        /**
         * 分頁查詢
         */
        @Test
        public void testNativeQueryPage(){
            // 創建查詢構建器 spring提供的
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 添加基本的分詞查詢
            queryBuilder.withQuery(QueryBuilders.termQuery("category", "手機"));
    
            // 初始化分頁參數  注意: 這裏的頁碼是從0開始, 不像我們之前是從1開始
            int page = 0;
            int size = 3;
            // 設置分頁參數
            queryBuilder.withPageable(PageRequest.of(page, size));
    
            // 執行搜索,獲取結果
            Page<Item> items = repository.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 testSort(){
            // 創建查詢構建器 spring提供的
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 添加 不分詞查詢(category等於手機)
            queryBuilder.withQuery(QueryBuilders.termQuery("category", "手機"));
    
            // 排序 根據price字段, 降序排序
            queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
    
            // 執行搜索,獲取結果
            Page<Item> items = repository.search(queryBuilder.build());
            // 打印總條數
            System.out.println(items.getTotalElements());
    
            items.forEach(System.out::println);
        }
    
        /**
         * 整合上面所有功能
         */
        @Test
        public void integration() {
            // 創建查詢構建器 spring提供的
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    
            // 結果過濾
            queryBuilder.withSourceFilter(new FetchSourceFilter(new String[] {"id", "title", "price"}, null));
    
            // 添加查詢條件
            queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米"));
    
            // 排序
            queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
    
            // 分頁
            queryBuilder.withPageable(PageRequest.of(0, 2));
    
            // 執行查詢
            Page<Item> list = repository.search(queryBuilder.build());
    
            // 獲取總元素個數
            System.out.println(list.getTotalElements());
    
            // 獲取總頁數
            System.out.println(list.getTotalPages());
    
            // 獲取當前頁
            System.out.println(list.getNumber());
    
            // 獲取每頁大小
            System.out.println(list.getSize());
    
            // 獲取當前頁內容
            System.out.println(list.getContent());
    
            // 獲取當前頁內容
            list.forEach(System.out::println);
        }
    
        /**
         * 聚合查詢
         */
        @Test
        public void testAgg() {
            // 創建查詢構建器 spring提供的
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    
            // 聚合名稱
            String aggName = "popularBrand";
    
            // 聚合
            queryBuilder.addAggregation(AggregationBuilders.terms(aggName).field("brand"));
    
            // 查詢並返回帶聚合的結果
            AggregatedPage<Item> items = template.queryForPage(queryBuilder.build(), Item.class);
    
            // 解析聚合
            Aggregations aggregations = items.getAggregations();
    
            // 獲取指定名稱的聚合(這裏用的實現類, 因爲用terms做的聚合, 被聚合的brand是String 所以這裏用的StringTerms)
            StringTerms terms = aggregations.get(aggName);
    
            // 獲取桶
            List<StringTerms.Bucket> buckets = terms.getBuckets();
    
            for (StringTerms.Bucket bucket : buckets) {
                System.out.println("key = " + bucket.getKey());
                System.out.println("docCount = " + bucket.getDocCount());
            }
    
        }
    
    }
    
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章