欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

4.6.springdata

程序员文章站 2022-03-25 10:34:16
...

1.Elasticsearch java客户端

Elasticsearch提供的Java客户端有一些不太方便的地方:

  • 很多地方需要拼接Json字符串,在java中拼接字符串有多恐怖你应该懂的
  • 需要自己把对象序列化为json存储
  • 查询到结果也需要自己反序列化为对象

因此,我们这里就不讲解原生的Elasticsearch客户端API了。

而是学习Spring提供的套件:Spring Data Elasticsearch。

1.1.简介

Spring Data Elasticsearch是Spring Data项目下的一个子模块。

查看 Spring Data的官网:http://projects.spring.io/spring-data/

4.6.springdata

Spring Data的使命是为数据访问提供熟悉且一致的基于Spring的编程模型,同时仍保留底层数据存储的特殊特性。

它使得使用数据访问技术,关系数据库和非关系数据库,map-reduce框架和基于云的数据服务变得容易。这是一个总括项目,其中包含许多特定于给定数据库的子项目。这些令人兴奋的技术项目背后,是由许多公司和开发人员合作开发的。

Spring Data 的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如MySQL),还是非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提高开发效率。

包含很多不同数据操作的模块:

4.6.springdata

Spring Data Elasticsearch的页面:https://projects.spring.io/spring-data-elasticsearch/

4.6.springdata

特征:

  • 支持Spring的基于@Configuration的java配置方式,或者XML配置方式
  • 提供了用于操作ES的便捷工具类**ElasticsearchTemplate**。包括实现文档到POJO之间的自动智能映射。
  • 利用Spring的数据转换服务实现的功能丰富的对象映射
  • 基于注解的元数据映射方式,而且可扩展以支持更多不同的数据格式
  • 根据持久层接口自动生成对应实现方法,无需人工编写基本操作代码(类似mybatis,根据接口自动得到实现)。当然,也支持人工定制查询

1.2.创建Demo工程

我们使用spring脚手架新建一个demo,学习Elasticsearch

pom依赖:
<?xml version="1.0" encoding="UTF-8"?>

4.0.0

    <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.4.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>
            <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>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.yml:

spring:
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 192.168.17.131:9300

启动类:

package com.leyou;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @description
 * @Author: mty
 * @Date:2020/5/10 0:18
 */
@SpringBootApplication
public class EsApplication {
    public static void main(String[] args) {
        SpringApplication.run(EsApplication.class);
    }
}

1.3实体类及注解

package com.leyou.es.pojo;

import lombok.Data;
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;

/**
 * @description
 * @Author: mty
 * @Date:2020/5/10 0:21
 */
@Data
@Document(indexName = "heima3",type = "item",shards = 1,replicas = 1)
public class Item {
    @Field(type = FieldType.Long)
    @Id
    Long id;
    @Field(type = FieldType.Text,analyzer = "ik_smart")
    String title;
    @Field(type = FieldType.Keyword)
    String category;
    @Field(type = FieldType.Keyword)
    String brand;
    @Field(type = FieldType.Double)
    Double price;
    @Field(type = FieldType.Keyword,index = false)
    String images;
}

1.4.创建索引和映射

创建测试类

package com.leyou.es.demo;

import com.leyou.es.pojo.Item;
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.ElasticsearchTemplate;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @description
 * @Author: mty
 * @Date:2020/5/10 0:24
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsTest {

    @Autowired
    ElasticsearchTemplate template;

    @Test
    public void testCreate(){
        // 创建索引库
        template.createIndex(Item.class);
        // 创建映射
        template.putMapping(Item.class);
    }
}

执行测试类,添加索引库和映射关系

查询:

GET /heima3/_mapping

返回结果:

{
  "heima3": {
    "mappings": {
      "item": {
        "properties": {
          "brand": {
            "type": "keyword"
          },
          "category": {
            "type": "keyword"
          },
          "id": {
            "type": "keyword"
          },
          "images": {
            "type": "keyword",
            "index": false
          },
          "price": {
            "type": "double"
          },
          "title": {
            "type": "text",
            "analyzer": "ik_smart"
          }
        }
      }
    }
  }
}

1.5.批量新增数据

1.新建一个ItemRepository接口继承ElasticsearchRepository

package com.leyou.es.repository;

import com.leyou.es.pojo.Item;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

/**
 * @description
 * @Author: mty
 * @Date:2020/5/10 0:49
 */
public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
}

2.批量新增数据

 @Test
    public void insetIndex(){
        List<Item> items = new ArrayList<>();
        items.add(new Item(1L,"小米手机7","手机","小米",3299.00,"http://image.leyou.com/123.jpg"));
        items.add(new Item(2L,"坚果手机R1","手机","锤子",3699.00,"http://image.leyou.com/123.jpg"));
        items.add(new Item(3L,"华为手机MATE10","手机","华为",4499.00,"http://image.leyou.com/123.jpg"));
        items.add(new Item(4L,"小米手机Min2S","手机","小米",4299.00,"http://image.leyou.com/123.jpg"));
        items.add(new Item(5L,"荣耀V10","手机","华为",2799.00,"http://image.leyou.com/123.jpg"));

        itemRepository.saveAll(items);
    }

说明:EsTest测试类需要引入:

Autowired
ItemRepository itemRepository;	

需要在Item实体类上加注解:

@AllArgsConstructor
@NoArgsConstructor

3.查询

GET /heima3/_search
{
  "query": {"match_all": {}}
}

4.返回结果:

{
  "took": 19,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 5,
    "max_score": 1,
    "hits": [
      {
        "_index": "heima3",
        "_type": "item",
        "_id": "1",
        "_score": 1,
        "_source": {
          "id": 1,
          "title": "小米手机7",
          "category": "手机",
          "brand": "小米",
          "price": 3299,
          "images": "http://image.leyou.com/123.jpg"
        }
      },
      {
        "_index": "heima3",
        "_type": "item",
        "_id": "2",
        "_score": 1,
        "_source": {
          "id": 2,
          "title": "坚果手机R1",
          "category": "手机",
          "brand": "锤子",
          "price": 3699,
          "images": "http://image.leyou.com/123.jpg"
        }
      },
      {
        "_index": "heima3",
        "_type": "item",
        "_id": "3",
        "_score": 1,
        "_source": {
          "id": 3,
          "title": "华为手机MATE10",
          "category": "手机",
          "brand": "华为",
          "price": 4499,
          "images": "http://image.leyou.com/123.jpg"
        }
      },
      {
        "_index": "heima3",
        "_type": "item",
        "_id": "4",
        "_score": 1,
        "_source": {
          "id": 4,
          "title": "小米手机Min2S",
          "category": "手机",
          "brand": "小米",
          "price": 4299,
          "images": "http://image.leyou.com/123.jpg"
        }
      },
      {
        "_index": "heima3",
        "_type": "item",
        "_id": "5",
        "_score": 1,
        "_source": {
          "id": 5,
          "title": "荣耀V10",
          "category": "手机",
          "brand": "华为",
          "price": 2799,
          "images": "http://image.leyou.com/123.jpg"
        }
      }
    ]
  }
}

1.6.查询数据

@Test
    public void testFind(){
        Iterable<Item> all = itemRepository.findAll();
        for (Item item : all) {
            System.out.println(item);
        }
    }

打印结果:

Item(id=1, title=小米手机7, category=手机, brand=小米, price=3299.0, images=http://image.leyou.com/123.jpg)
Item(id=2, title=坚果手机R1, category=手机, brand=锤子, price=3699.0, images=http://image.leyou.com/123.jpg)
Item(id=3, title=华为手机MATE10, category=手机, brand=华为, price=4499.0, images=http://image.leyou.com/123.jpg)
Item(id=4, title=小米手机Min2S, category=手机, brand=小米, price=4299.0, images=http://image.leyou.com/123.jpg)
Item(id=5, title=荣耀V10, category=手机, brand=华为, price=2799.0, images=http://image.leyou.com/123.jpg)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Wrsm0HY-1589045746535)(assets/testFind()].png)

1.7.复杂查询,根据价格范围查询(自定义查询)

  • 在接口中写一个根据价格范围查询的方法

    List<Item> findByPriceBetween(Double start, Double end);

  • 测试范围查询

      @Test
      public void testFindBy(){
      List<Item> itemList = itemRepository.findByPriceBetween(2000d, 4000d);
      for (Item item : itemList) {
      System.out.println(item);
      }
      }
    
  • 结果

      Item(id=1, title=小米手机7, category=手机, brand=小米, price=3299.0, images=http://image.leyou.com/123.jpg)
      Item(id=2, title=坚果手机R1, category=手机, brand=锤子, price=3699.0, images=http://image.leyou.com/123.jpg)
      Item(id=5, title=荣耀V10, category=手机, brand=华为, price=2799.0, images=http://image.leyou.com/123.jpg)
    

0d);
for (Item item : itemList) {
System.out.println(item);
}
}

  • 结果

      Item(id=1, title=小米手机7, category=手机, brand=小米, price=3299.0, images=http://image.leyou.com/123.jpg)
      Item(id=2, title=坚果手机R1, category=手机, brand=锤子, price=3699.0, images=http://image.leyou.com/123.jpg)
      Item(id=5, title=荣耀V10, category=手机, brand=华为, price=2799.0, images=http://image.leyou.com/123.jpg)
    

Spring Data Elasticsearch 这种自定义查询不能使用聚合,聚合要使用elasticsearch的原生API

推荐阅读