Elastic Stack--08--SpringData框架
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- SpringData
- [官网: https://spring.io/projects/spring-data](https://spring.io/projects/spring-data)
- Spring Data Elasticsearch 介绍
- 1.SpringData-代码功能集成
- 1.增加依赖
- 2.增加配置文件
- 3. 数据实体类
- 让自定义的类型和ElasticSearch中的一个索引产生关联
- 案例解析
- 4.配置类
- 5.DAO 数据访问对象
- 2.SpringData---索引操作
- 索引操作
- 创建索引
- 删除索引
- 3.SpringData---文档操作(ElasticSearchRepository)
- ==本文仅展示使用ElasticsearchRepository的操作==
- 文档操作
- 文档搜索
SpringData
- Spring Data是一个用于简化数据库、非关系型数据库、索引库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持 map-reduce框架和云计算数据服务。
- Spring Data可以极大的简化JPA(Elasticsearch…)的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。
官网: https://spring.io/projects/spring-data
Spring Data Elasticsearch 介绍
- Spring Data Elasticsearch基于Spring Data API简化 Elasticsearch 操作,将原始操作Elasticsearch 的客户端API进行封装。Spring Data为Elasticsearch 项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储索引库数据访问层。
https://spring.io/projects/spring-data-elasticsearch
1.SpringData-代码功能集成
1.增加依赖
4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.6.RELEASE com.lun SpringDataWithES 1.0.0-SNAPSHOT 8 8 org.projectlombok lombok org.springframework.boot spring-boot-starter-data-elasticsearch org.springframework.boot spring-boot-devtools runtime true org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-test junit junit org.springframework spring-test
2.增加配置文件
# es 服务地址 elasticsearch.host=127.0.0.1 # es 服务端口 elasticsearch.port=9200 # 配置日志级别,开启 debug 日志 logging.level.com.atguigu.es=debug
3. 数据实体类
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; 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; @Data @NoArgsConstructor @AllArgsConstructor @ToString @Document(indexName = "shopping", shards = 3, replicas = 1) public class Product { //必须有 id,这里的 id 是全局唯一的标识,等同于 es 中的"_id" @Id private Long id;//商品唯一标识 /** * type : 字段数据类型 * analyzer : 分词器类型 * index : 是否索引(默认:true) * Keyword : 短语,不进行分词 */ @Field(type = FieldType.Text, analyzer = "ik_max_word") private String title;//商品名称 @Field(type = FieldType.Keyword) private String category;//分类名称 @Field(type = FieldType.Double) private Double price;//商品价格 @Field(type = FieldType.Keyword, index = false) private String images;//图片地址 }
让自定义的类型和ElasticSearch中的一个索引产生关联
- Document - spring data elasticsearch提供的注解, 描述类型,说明类型和索引的关系。
- indexName - 对应的索引的名称。 必要属性。
- shards - 创建索引时,设置的主分片数量。 默认5
- replicas - 创建索引时,设置的副本分片数量。 默认1
- type - 对应的类型的名称。
案例解析
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; /** * 自定义类型,商品。 * 让自定义的类型和ElasticSearch中的一个索引产生关联。 * Document - spring data elasticsearch提供的注解, 描述类型,说明类型和索引的关系。 * indexName - 对应的索引的名称。 必要属性。 * shards - 创建索引时,设置的主分片数量。 默认5 * replicas - 创建索引时,设置的副本分片数量。 默认1 * type - 对应的类型的名称。 * @create 2021-02-24 上午 10:42 */ @Document(indexName = "hrt-item", shards = 2, replicas = 2, type = "item") public class Item { /** * Id注解是Spring Data核心工程提供的,是所有的Spring Data二级子工程通用的。 * 代表主键字段。 */ @Id private String id; /** * Field注解,描述实体类型中属性和ES索引中字段的关系。 * 且可以为这个字段配置自定义映射mapping * 这个自定义映射必须通过代码逻辑调用设置映射的API才能生效。 * name - 索引中对应的字段名称,默认和属性同名。 * type - 索引中字段的类型,默认是FieldType.Auto,代表ES自动映射类型。 * analyzer - 字段的分词器名称,默认是standard。 * fielddata - 是否开启正向索引。默认关闭。 * 默认只为文本类型的字段创建反向索引,提供快速搜索逻辑。 * fielddata设置为true,则会额外创建一个正向索引,支持排序。 * index - 是否创建默认的反向索引或正向索引。 text文本类型字段默认创建反向索引,其他创建正向索引。 * 没有索引,就不能作为搜索条件。 */ @Field(name = "title", type = FieldType.Text, analyzer = "ik_max_word", fielddata = true) private String title; // 商品名称,需要中文分词,且偶尔需要排序, 常用搜索条件之一 @Field(name = "sellPoint", type = FieldType.Text, analyzer = "ik_max_word") private String sellPoint; // 卖点, 需要中文分词, 常用搜索条件之一 @Field(type = FieldType.Long) private Long price; // 单价 @Field(type = FieldType.Integer, index = false) private int num; // 库存 }
4.配置类
- ElasticsearchRestTemplate是spring-data-elasticsearch项目中的一个类,和其他spring项目中的
template类似。
- 在新版的spring-data-elasticsearch 中,ElasticsearchRestTemplate 代替了原来的ElasticsearchTemplate。
- 原因是ElasticsearchTemplate基于TransportClient,TransportClient即将在8.x 以后的版本中移除。所以,我们推荐使用ElasticsearchRestTemplate。
- ElasticsearchRestTemplate基于RestHighLevelClient客户端的。需要自定义配置类,继承AbstractElasticsearchConfiguration,并实现elasticsearchClient()抽象方法,创建RestHighLevelClient对象。
需要自定义配置类,继承AbstractElasticsearchConfiguration,并实现elasticsearchClient()抽象方法,创建RestHighLevelClient对象。
import lombok.Data; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; @ConfigurationProperties(prefix = "elasticsearch") @Configuration @Data public class ElasticsearchConfig extends AbstractElasticsearchConfiguration{ private String host ; private Integer port ; //重写父类方法 @Override public RestHighLevelClient elasticsearchClient() { RestClientBuilder builder = RestClient.builder(new HttpHost(host, port)); RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder); return restHighLevelClient; } }
5.DAO 数据访问对象
import com.lun.model.Product; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; @Repository public interface ProductDao extends ElasticsearchRepository{ }
2.SpringData—索引操作
索引操作
import com.lun.model.Product; 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.ElasticsearchRestTemplate; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringDataESIndexTest { //注入 ElasticsearchRestTemplate @Autowired private ElasticsearchRestTemplate restTemplate; //创建索引并增加映射配置 @Test public void createIndex(){ //创建索引,系统初始化会自动创建索引 System.out.println("创建索引"); } @Test public void deleteIndex(){ //创建索引,系统初始化会自动创建索引 boolean flg = restTemplate.deleteIndex(Product.class); System.out.println("删除索引 = " + flg); } }
创建索引
- createIndex(): 创建索引,创建出来的索引是不带有 mapping 信息的。返回值表示是 否创建成功
- putMapping():为已有的索引添加 mapping 信息。不具备创建索引的能力。返回值表 示是否创建成功
/** * 创建索引,并设置映射。 * 需要通过两次访问实现,1、创建索引;2、设置映射。 */ @Test public void testInitIndex(){ // 创建索引,根据类型上的Document注解创建 boolean isCreated = restTemplate.createIndex(Item.class); // 设置映射,根据属性上的Field注解设置 0201 boolean isMapped = restTemplate.putMapping(Item.class); System.out.println("创建索引是否成功:" + isCreated); System.out.println("设置映射是否成功:" + isMapped); }
删除索引
/** * 删除索引 */ @Test public void deleteIndex(){ // 扫描Item类型上的Document注解,删除对应的索引。 boolean isDeleted = restTemplate.deleteIndex(Item.class); System.out.println("删除Item对应索引是否成功:" + isDeleted); // 直接删除对应名称的索引。 isDeleted = restTemplate.deleteIndex("test_index3"); System.out.println("删除default_index索引是否成功:" + isDeleted); }
3.SpringData—文档操作(ElasticSearchRepository)
spring-data-elasticsearch是比较好用的一个elasticsearch客户端,本文介绍如何使用它来操作ES。本文使用spring-boot-starter-data-elasticsearch,它内部会引入spring-data-elasticsearch。
Spring Data ElasticSearch有下边这几种方法操作ElasticSearch:
- ElasticsearchRepository(传统的方法,可以使用)
- ElasticsearchRestTemplate(推荐使用。基于RestHighLevelClient)
- ElasticsearchTemplate(ES7中废弃,不建议使用。基于TransportClient)
- RestHighLevelClient(推荐度低于ElasticsearchRestTemplate,因为API不够高级)
- TransportClient(ES7中废弃,不建议使用)
本文仅展示使用ElasticsearchRepository的操作
文档操作
import com.lun.dao.ProductDao; import com.lun.model.Product; 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.domain.Sort; import org.springframework.test.context.junit4.SpringRunner; import java.util.ArrayList; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class SpringDataESProductDaoTest { @Autowired private ProductDao productDao; /** * 新增 */ @Test public void save(){ Product product = new Product(); product.setId(2L); product.setTitle("华为手机"); product.setCategory("手机"); product.setPrice(2999.0); product.setImages("http://www.atguigu/hw.jpg"); productDao.save(product); } //POSTMAN, GET http://localhost:9200/product/_doc/2 //修改 @Test public void update(){ Product product = new Product(); product.setId(2L); product.setTitle("小米 2 手机"); product.setCategory("手机"); product.setPrice(9999.0); product.setImages("http://www.atguigu/xm.jpg"); productDao.save(product); } //POSTMAN, GET http://localhost:9200/product/_doc/2 //根据 id 查询 @Test public void findById(){ Product product = productDao.findById(2L).get(); System.out.println(product); } @Test public void findAll(){ Iterable products = productDao.findAll(); for (Product product : products) { System.out.println(product); } } //删除 @Test public void delete(){ Product product = new Product(); product.setId(2L); productDao.delete(product); } //POSTMAN, GET http://localhost:9200/product/_doc/2 //批量新增 @Test public void saveAll(){ List productList = new ArrayList(); for (int i = 0; i
term 查询 分页
import com.lun.dao.ProductDao; import com.lun.model.Product; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.TermQueryBuilder; 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.PageRequest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringDataESSearchTest { @Autowired private ProductDao productDao; /** * term 查询 * search(termQueryBuilder) 调用搜索方法,参数查询构建器对象 */ @Test public void termQuery(){ TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "小米"); Iterable products = productDao.search(termQueryBuilder); for (Product product : products) { System.out.println(product); } } /** * term 查询加分页 */ @Test public void termQueryByPage(){ int currentPage= 0 ; int pageSize = 5; //设置查询分页 PageRequest pageRequest = PageRequest.of(currentPage, pageSize); TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "小米"); Iterable products = productDao.search(termQueryBuilder,pageRequest); for (Product product : products) { System.out.println(product); } } }
文档搜索
package com.example.demo.controller; import com.example.demo.dao.BlogRepository; import com.example.demo.entity.Blog; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.Date; import java.util.List; @Api(tags = "增删改查(文档)") @RestController @RequestMapping("crud") public class CrudController { @Autowired private BlogRepository blogRepository; @ApiOperation("添加单个文档") @PostMapping("addDocument") public Blog addDocument() { Long id = 1L; Blog blog = new Blog(); blog.setBlogId(id); blog.setTitle("Spring Data ElasticSearch学习教程" + id); blog.setContent("这是添加单个文档的实例" + id); blog.setAuthor("Tony"); blog.setCategory("ElasticSearch"); blog.setCreateTime(new Date()); blog.setStatus(1); blog.setSerialNum(id.toString()); return blogRepository.save(blog); } @ApiOperation("添加多个文档") @PostMapping("addDocuments") public Object addDocuments(Integer count) { List blogs = new ArrayList(); for (int i = 1; i Long id = (long)i; Blog blog = new Blog(); blog.setBlogId(id); blog.setTitle("Spring Data ElasticSearch学习教程" + id); blog.setContent("这是添加单个文档的实例" + id); blog.setAuthor("Tony"); blog.setCategory("ElasticSearch"); blog.setCreateTime(new Date()); blog.setStatus(1); blog.setSerialNum(id.toString()); blogs.add(blog); } return blogRepository.saveAll(blogs); } /** * 跟新增是同一个方法。若id已存在,则修改。 * 无法只修改某个字段,只能覆盖所有字段。若某个字段没有值,则会写入null。 * @return 成功写入的数据 */ @ApiOperation("修改单个文档") @PostMapping("editDocument") public Blog editDocument() { Long id = 1L; Blog blog = new Blog(); blog.setBlogId(id); blog.setTitle("Spring Data ElasticSearch学习教程" + id); blog.setContent("这是修改单个文档的实例" + id); // blog.setAuthor("Tony"); // blog.setCategory("ElasticSearch"); // blog.setCreateTime(new Date()); // blog.setStatus(1); // blog.setSerialNum(id.toString()); return blogRepository.save(blog); } @ApiOperation("查找单个文档") @GetMapping("findById") public Blog findById(Long id) { return blogRepository.findById(id).get(); } @ApiOperation("删除单个文档") @PostMapping("deleteDocument") public String deleteDocument(Long id) { blogRepository.deleteById(id); return "success"; } @ApiOperation("删除所有文档") @PostMapping("deleteDocumentAll") public String deleteDocumentAll() { blogRepository.deleteAll(); return "success"; } }
- ElasticsearchRestTemplate是spring-data-elasticsearch项目中的一个类,和其他spring项目中的
- Spring Data Elasticsearch基于Spring Data API简化 Elasticsearch 操作,将原始操作Elasticsearch 的客户端API进行封装。Spring Data为Elasticsearch 项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储索引库数据访问层。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。