本文使用内容 springBoot2.2.5.RELEASE版本 Elasticsearch7.6.2 linux版本的 SpringDataElasticSearch与Springboot版本对应
此处版本
2.2.5.RELEASE
org.springframework.boot
spring-boot-starter-parent
2.2.5.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-data-elasticsearch
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
spring:
elasticsearch:
rest:
uris: http://192.168.0.211:9200
此处的ip:端口 是自己的Elasticsearch的,如果为集群可以以逗号(,)隔开
package cn.cqsw.elasticsearch.pojo;
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;
import java.io.Serializable;
@Document(indexName = "item" , type = "_doc",shards = 1,replicas = 0)
public class Item implements Serializable {
@Id //注意此处的@Id必须为springframework包下面的id import org.springframework.data.annotation.Id;
Long id;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
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; // 图片地址
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 getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getImages() {
return images;
}
public void setImages(String images) {
this.images = images;
}
public Item() {
}
public Item(Long id, String title, String category, String brand, Double price, String images) {
this.id = id;
this.title = title;
this.category = category;
this.brand = brand;
this.price = price;
this.images = images;
}
@Override
public String toString() {
return "Item{" +
"id=" + id +
", title='" + title + '\'' +
", category='" + category + '\'' +
", brand='" + brand + '\'' +
", price=" + price +
", images='" + images + '\'' +
'}';
}
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
不明白为什么可以看一些Spring-Data文档
@SpringBootApplication
public class ElasticSearchApplication {
public static void main(String[] args) {
SpringApplication.run(ElasticSearchApplication.class);
}
}
此处使用
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- 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 = this.itemRepository.findById(1L);
System.out.println("item.get() = " + item.get());
}
/**
* 查询并排序
*/
@Test
public void findAllSort() {
Iterable
- items = this.itemRepository.findAll(Sort.by("price").descending());
items.forEach(System.out::println);
}
/**
* 根据title查询
*/
@Test
public void findByTitle() {
Iterable
- items = this.itemRepository.findByTitle("手机");
items.forEach(System.out::println);
}
/**
* 查询价格区间
*/
@Test
public void findByPrice() {
List
- byPriceBetween = this.itemRepository.findByPriceBetween(3699d, 4499d);
byPriceBetween.forEach(System.out::println);
}
/**
* 添加测试数据
*/
@Test
public void indexList() {
List
- 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
- 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
- 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
- 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
- itemPage = (AggregatedPage
- )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
- itemPage = (AggregatedPage
- )this.itemRepository.search(queryBuilder.build());
/*
解析聚合结果集,根据聚合的类型以及字段类型,要进行强转,不然无法获取桶
brand-是字符串类型的,聚合类型是词条类型的
brandAgg-通过聚合名称获取聚合对象
使用StringTerms强转的时候出现错误
*/
StringTerms brandAgg =(StringTerms) itemPage.getAggregation("brandAgg");
//获取桶
List
buckets = brandAgg.getBuckets();
//遍历输出
buckets.forEach(bucket -> {
System.out.println("bucket.getKeyAsString() = " + bucket.getKeyAsString());
//获取条数
System.out.println("bucket.getDocCount() = " + bucket.getDocCount());
//获取子聚合的map集合:key-聚合名称,value-对应的子聚合对象
Map stringAggregationMap = bucket.getAggregations().asMap();
/*
以前使用的InternalAvg强转出现转换异常
*/
ParsedAvg price_avg =(ParsedAvg) stringAggregationMap.get("price_avg");
System.out.println("price_avg.getValue() = " + price_avg.getValue());
});
}
}
虽然为转载,但来自同一作者