最完整的springboot2.2.x.RELEASE整合springDataElasticsearch 7.6.2
本文使用内容 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、创建实体类对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
注解参数含义解释
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()); }); } }
本文来自博客园,作者:BaldHead,转载请注明原文链接:https://www.cnblogs.com/strict/p/12652308.html