• Spring Data ElasticSearch(一)


    1. Spring Data简介

    Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。 Spring Data可以极大的简化JPA的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一
    些常用的功能。

    Spring Data的官网:

    http://projects.spring.io/spring-data/

    Spring Data常用的功能模块如下:
    在这里插入图片描述
    在这里插入图片描述

    1.2 Spring Data ElasticSearch

    Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data ElasticsearchPOJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。

    官方网站:

    http://projects.spring.io/spring-data-elasticsearch/

    2. 简单查询案例

    1)导入Spring Data ElasticSearch坐标

    <?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">
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.16.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>SpringData_ElasticSearch</artifactId>
        <properties>
            <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>
    
    </project>
    
    • 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

    2)启动器配置文件

    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    配置文件

    spring:
     data:
      elasticsearch:
       cluster-name: my-elasticsearch
       cluster-nodes: 192.168.45.131:9300
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3)编写实体Article

    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;
    
    @Document(indexName = "blog4",type="article")
    public class Article {
        @Id
        @Field(type = FieldType.Long, store = true)
        private long id;
        @Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
        private String title;
        @Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
        private String content;
    
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        @Override
        public String toString() {
            return "Article{" +
                    "id=" + id +
                    ", title='" + title + '\'' +
                    ", content='" + content + '\'' +
                    '}';
        }
    }
    
    
    • 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

    4)编写Dao
    方法命名规则查询的基本语法findBy + 属性 + 关键词 + 连接符

    关键字命名规则解释示例
    andfindByField1AndField2根据Field1和Field2获得数据findByTitleAndContent
    orfindByField1OrField2根据Field1或Field2获得数据findByTitleOrContent
    isfindByField根据Field获得数据findByTitle
    notfindByFieldNot根据Field获得补集数据findByTitleNot
    betweenfindByFieldBetween获得指定范围的数据findByPriceBetween
    lessThanEqualfindByFieldLessThan获得小于等于指定值的数据findByPriceLessThan
    import com.da.domain.Article;
    
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    
    import org.springframework.data.domain.Pageable;
    import java.util.List;
    
    public interface ArticelRepository extends ElasticsearchRepository<Article,Long> {
    public List<Article> findByTitle(String title);
    public List<Article> findByTitleOrContent(String title,String content);
    public List<Article> findAllByContent(String content, Pageable pageable);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6)创建测试类

    import com.da.dao.ArticelRepository;
    import com.da.domain.Article;
    import org.elasticsearch.index.query.QueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.List;
    import java.util.Optional;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class Test {
        @Autowired
        ArticelRepository articelRepository;
        @Autowired
        ElasticsearchTemplate template;
    
        @org.junit.Test
        public void createIndex() {
            //创建索引并配置映射关系
            template.createIndex(Article.class);
            //配置映射关系
            // template.putMapping(Article.class);
        }
    
        @org.junit.Test
        public void addDocument() {
    
            for (int i = 11; i < 20; i++) {
                Article article = new Article();
                article.setId(i);
                article.setTitle("女护士路遇昏迷男子跪地抢救:救人是职责更是本能" + i);
                article.setContent("这是一个美丽的女护士妹妹" + i);
                //把文档写入索引库
                articelRepository.save(article);
            }
        }
    
        @org.junit.Test
        public void deleteDocumentById() {
            //删除一个
            //articelRepository.deleteById(1L);
            //删除全部
            articelRepository.deleteAll();
        }
    
        @org.junit.Test
        public void findAll() {
            Iterable<Article> all = articelRepository.findAll();
            all.forEach(a -> System.out.println(a));
        }
    
        @org.junit.Test
        public void findFindById() {
            Optional<Article> byId = articelRepository.findById(14L);
            Article article = byId.get();
            System.out.println(article);
    
        }
    
        @org.junit.Test
        public void findByTitle() {
            List<Article> s = articelRepository.findByTitle("女护士");
            s.stream().forEach(a -> System.out.println(a));
    
        }
    
        @org.junit.Test
        public void findByContent() {
            Pageable pageable = PageRequest.of(1, 5);
            System.out.println("------------------");
            List<Article> a = articelRepository.findAllByContent("美丽", pageable);
            a.forEach(a1 -> System.out.println(a1));
        }
    
        @org.junit.Test
        public void testNativeSearchQuery() {
    //创建一个查询对象
            NativeSearchQuery query = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.queryStringQuery("女护士")
                            .defaultField("title")).withPageable(PageRequest.of(0, 15))
                    .build();
            //执行查询
            List<Article> list = template.queryForList(query, Article.class);
            list.forEach(a -> System.out.println(a));
    
        }
    
    }
    
    
    • 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
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    3. 聚合查询

    实体类

    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;
    
    @Document(indexName = "blog4",   type = "car")
    public class Car {
        @Id
        @Field(type = FieldType.Long, store = true)
        private Long id;
        @Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
        private String name;
        @Field(type = FieldType.Text, store = true, analyzer = "ik_smart", fielddata
                = true)
        private String color;
        @Field(type = FieldType.Text, store = true, analyzer = "ik_smart", fielddata
                = true)
        private String brand;
        @Field(type = FieldType.Double, store = true)
        private Double price;
    public Car(){}
        public Car(Long id, String name, String color, String brand, Double price) {
            this.id = id;
            this.name = name;
            this.color = color;
            this.brand = brand;
            this.price = price;
        }
    
        public Double getPrice() {
            return price;
        }
    
        public void setPrice(Double price) {
            this.price = price;
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getColor() {
            return color;
        }
    
        public void setColor(String color) {
            this.color = color;
        }
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        @Override
        public String toString() {
            return "Car{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", color='" + color + '\'' +
                    ", brand='" + brand + '\'' +
                    ", price=" + price +
                    '}';
        }
    }
    
    
    • 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
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    Dao

    import com.da.domain.Car;
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    
    public interface CarRepository extends ElasticsearchRepository<Car,Long> {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    初始化索引库

    import com.da.dao.CarRepository;
    import com.da.domain.Car;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.search.aggregations.Aggregation;
    import org.elasticsearch.search.aggregations.AggregationBuilders;
    import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
    import org.elasticsearch.search.aggregations.metrics.avg.InternalAvg;
    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.elasticsearch.core.aggregation.AggregatedPage;
    import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class CarTest {
        @Autowired
        CarRepository carDao;
    
        @Test
        public void saveCar(){
            carDao.save(new Car(1l, "比亚迪A1", "红色", "比亚迪", 50000d));
            carDao.save(new Car(2l, "比亚迪A2", "白色", "比亚迪", 70000d));
            carDao.save(new Car(3l, "比亚迪A3", "白色", "比亚迪", 80000d));
            carDao.save(new Car(4l, "比亚迪A4", "红色", "比亚迪", 60000d));
            carDao.save(new Car(5l, "比亚迪A5", "红色", "比亚迪", 90000d));
            carDao.save(new Car(6l, "宝马A1", "红色", "宝马", 10000d));
            carDao.save(new Car(7l, "宝马A2", "黑色", "宝马", 20000d));
            carDao.save(new Car(8l, "宝马A3", "黑色", "宝马", 30000d));
            carDao.save(new Car(9l, "宝马A4", "红色", "宝马", 40000d));
            carDao.save(new Car(10l, "宝马A5", "红色", "宝马", 50000d));
            carDao.save(new Car(11l, "奔驰A1", "红色", "奔驰", 10000d));
            carDao.save(new Car(12l, "奔驰A2", "黑色", "奔驰", 20000d));
            carDao.save(new Car(13l, "奔驰A3", "黑色", "奔驰", 30000d));
            carDao.save(new Car(14l, "奔驰A4", "红色", "奔驰", 40000d));
            carDao.save(new Car(15l, "奔驰A5", "红色", "奔驰", 50000d));
    
        }
       }
    
    
    • 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

    划分桶

    GET /car_index/car/_search
    {
    "query": {
    "bool": {
    "should": [
    {
    "match_all": {}
    }
    ]
    }
    },
    "aggs": {
    "group_by_bland": {
    "terms": {
    "field": "color"
    }
    }
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    桶内度量

    GET /car_index/car/_search
    {
    "query": {
    "bool": {
    "should": [
    {
    "match_all": {}
    }
    ]
    }
    },
    "aggs": {
    "group_by_bland": {
    "terms": {
    "field": "color"
    },
    "aggs": {
    "avg_price": {
    "avg": {
    "field": "price"
    }
    }
    }
    }
    }
    }
    
    • 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

    Spring Data ElasticSearch代码实现

    1.划分桶

    @Test
        public void testQuerySelfAggs(){
            //查询条件的构造器
            NativeSearchQueryBuilder query=new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.matchAllQuery());
            //排除所有的字段查询
            query.withSourceFilter(new FetchSourceFilter(new String[]{},null));
    
            //添加聚合条件
            query.addAggregation(AggregationBuilders.terms("group_by_color").field("color"));
            //执行查询,把查询结果直接转为聚合page
            AggregatedPage<Car> a=(AggregatedPage<Car>)carDao.search(query.build());
            //从所有的聚合中获取对应名称的聚合
            StringTerms terms=(StringTerms) a.getAggregation("group_by_color");
            //从聚合的结果中获取所有的桶信息
            List<StringTerms.Bucket> buckets = terms.getBuckets();
              for(StringTerms.Bucket bucket:buckets){
                  String keyAsString = bucket.getKeyAsString();
                  long docCount = bucket.getDocCount();
                  System.out.println("color:"+keyAsString+"   ======>"+"总数:"+docCount);
              }
    
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2.桶内度量

     @Test
        public void testQuerySelfSubAggs(){
            //查询条件的构造器
            NativeSearchQueryBuilder query=new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery());
            //排除所有的字段查询
            query.withSourceFilter(new FetchSourceFilter(new String[]{},null));
            //添加聚合条件
            query.addAggregation(AggregationBuilders.terms("group_by_color").field("color")
                    .subAggregation(AggregationBuilders.avg("avg_price").field("price")));
            //执行查询,把查询结果直接转为聚合page
            AggregatedPage<Car> a=(AggregatedPage<Car>) carDao.search(query.build());
            //从所有的聚合中获取对应名称的聚合
            StringTerms t=(StringTerms)a.getAggregation("group_by_color");
            //从聚合的结果中获取所有的桶信息
            List<StringTerms.Bucket> buckets = t.getBuckets();
            for(StringTerms.Bucket bucket:buckets){
                String keyAsString = bucket.getKeyAsString();
                long docCount = bucket.getDocCount();
                InternalAvg avg_price =(InternalAvg)bucket.getAggregations().asMap().get("avg_price");
                System.out.println("color:"+keyAsString+"=====>"+"数量:"+docCount+"   ====>avg_price"+avg_price);
            }
    
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    详解二叉搜索树【C++实现】
    pandas---数据结构(Series、DataFrame 和 MultiIndex)创建方式、属性
    wvp平台 视频设备接入注意点
    Mocha + Chai 测试环境配置,支持 ES6 语法
    Conda 命令小表格
    4. Java并发编程-管程
    高级IO(Linux)
    IMBroker —— 基于FaaS的跨平台群消息工具
    猿创征文 |《深入浅出Vue.js》打卡Day4
    webrtc快速入门——使用 WebRTC 拍摄静止的照片
  • 原文地址:https://blog.csdn.net/daai5201314/article/details/126456150