突然发现 项目中的es配置过时了 查看官方文档后发现
官方将在未来的8.0版本后移除之前的api 推荐使用RestHighLevelClient
导入依赖 maven坐标
<!--添加ElasticSearch依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!--引入lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
按照官方文档进行配置
@Configuration
@EnableElasticsearchRepositories
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "item_index", type = "item"/*, shards = 1, replicas = 0*/)
public class ItemEntity {
@Id
private Long id;
@Field(type = FieldType.Text/*, analyzer = "ik_max_word"*/)
private String title; //标题
@Field(type = FieldType.Keyword)
private String category;// 分类
@Field(type = FieldType.Keyword)
private String brand; // 品牌
@Field(type = FieldType.Double)
private Double price; // 价格
@Field(index = false, type = FieldType.Keyword)
private String images; // 图片地址
}
数据增删改查
public interface ItemRepository extends ElasticsearchRepository<ItemEntity, Long> {
/**
* 根据价格区间查询
*
* @param price1
* @param price2
* @return
*/
List<ItemEntity> findByPriceBetween(double price1, double price2);
}
网上随处可见的测试用例
@RunWith(SpringRunner.class)
@SpringBootTest
public class RestTests {
/*@Autowired
private ElasticsearchRestTemplate mRestTemplate;*/
@Autowired
private ItemRepository itemRepository;
/**
* 创建索引
*/
/*@Test
public void createIndex() {
// 创建索引,会根据Item类的@Document注解信息来创建
mRestTemplate.createIndex(ItemEntity.class);
// 配置映射,会根据Item类中的id、Field等字段来自动完成映射
mRestTemplate.putMapping(ItemEntity.class);
}*/
/**
* 新增
*/
@Test
public void insert() {
ItemEntity item = new ItemEntity(1L, "小米手机7", "手机", "小米", 2999.00, "https://img12.360buyimg.com/n1/s450x450_jfs/t1/14081/40/4987/124705/5c371b20E53786645/c1f49cd69e6c7e6a.jpg");
itemRepository.save(item);
}
/**
* 批量新增
*/
@Test
public void insertList() {
List<ItemEntity> list = new ArrayList<>();
list.add(new ItemEntity(2L, "坚果手机R1", "手机", "锤子", 3999.00, "https://img12.360buyimg.com/n1/s450x450_jfs/t1/14081/40/4987/124705/5c371b20E53786645/c1f49cd69e6c7e6a.jpg"));
list.add(new ItemEntity(3L, "华为META20", "手机", "华为", 4999.00, "https://img12.360buyimg.com/n1/s450x450_jfs/t1/14081/40/4987/124705/5c371b20E53786645/c1f49cd69e6c7e6a.jpg"));
list.add(new ItemEntity(4L, "iPhone X", "手机", "iPhone", 5100.00, "https://img12.360buyimg.com/n1/s450x450_jfs/t1/14081/40/4987/124705/5c371b20E53786645/c1f49cd69e6c7e6a.jpg"));
list.add(new ItemEntity(5L, "iPhone XS", "手机", "iPhone", 5999.00, "https://img12.360buyimg.com/n1/s450x450_jfs/t1/14081/40/4987/124705/5c371b20E53786645/c1f49cd69e6c7e6a.jpg"));
// 接收对象集合,实现批量新增
itemRepository.saveAll(list);
}
/**
* 修改
*
* :修改和新增是同一个接口,区分的依据就是id,这一点跟我们在页面发起PUT请求是类似的。
*/
/**
* 删除所有
*/
@Test
public void delete() {
itemRepository.deleteAll();
}
/**
* 基本查询
*/
@Test
public void query() {
// 查询全部,并按照价格降序排序
Iterable<ItemEntity> items = itemRepository.findAll(Sort.by("price").descending());
items.forEach(item -> System.out.println("item = " + item));
}
/**
* 自定义方法
*/
@Test
public void queryByPriceBetween() {
// 根据价格区间查询
List<ItemEntity> list = itemRepository.findByPriceBetween(5000.00, 6000.00);
list.forEach(item -> System.out.println("item = " + item));
}
/**
* 自定义查询
*/
@Test
public void search() {
// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本分词查询
queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米手机"));
// 搜索,获取结果
Page<ItemEntity> items = itemRepository.search(queryBuilder.build());
// 总条数
long total = items.getTotalElements();
System.out.println("total = " + total);
items.forEach(item -> System.out.println("item = " + item));
}
/**
* 分页查询
*/
@Test
public void searchByPage() {
// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本分词查询
queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
// 分页:
int page = 0;
int size = 2;
queryBuilder.withPageable(PageRequest.of(page, size));
// 搜索,获取结果
Page<ItemEntity> items = itemRepository.search(queryBuilder.build());
long total = items.getTotalElements();
System.out.println("总条数 = " + total);
System.out.println("总页数 = " + items.getTotalPages());
System.out.println("当前页:" + items.getNumber());
System.out.println("每页大小:" + items.getSize());
items.forEach(item -> System.out.println("item = " + item));
}
/**
* 排序
*/
@Test
public void searchAndSort() {
// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本分词查询
queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
// 排序
queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC));
// 搜索,获取结果
Page<ItemEntity> items = this.itemRepository.search(queryBuilder.build());
// 总条数
long total = items.getTotalElements();
System.out.println("总条数 = " + total);
items.forEach(item -> System.out.println("item = " + item));
}
/**
* 聚合为桶
*/
@Test
public void testAgg() {
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 不查询任何结果
queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
// 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
queryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand"));
// 2、查询,需要把结果强转为AggregatedPage类型
AggregatedPage<ItemEntity> aggPage = (AggregatedPage<ItemEntity>) itemRepository.search(queryBuilder.build());
// 3、解析
// 3.1、从结果中取出名为brands的那个聚合,
// 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
// 3.2、获取桶
List<StringTerms.Bucket> buckets = agg.getBuckets();
// 3.3、遍历
for (StringTerms.Bucket bucket : buckets) {
// 3.4、获取桶中的key,即品牌名称
System.out.println(bucket.getKeyAsString());
// 3.5、获取桶中的文档数量
System.out.println(bucket.getDocCount());
}
}
/**
* 嵌套聚合,求平均值
*/
@Test
public void testSubAgg() {
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 不查询任何结果
queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
// 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
queryBuilder.addAggregation(
AggregationBuilders.terms("brands").field("brand")
.subAggregation(AggregationBuilders.avg("priceAvg").field("price")) // 在品牌聚合桶内进行嵌套聚合,求平均值
);
// 2、查询,需要把结果强转为AggregatedPage类型
AggregatedPage<ItemEntity> aggPage = (AggregatedPage<ItemEntity>) this.itemRepository.search(queryBuilder.build());
// 3、解析
// 3.1、从结果中取出名为brands的那个聚合,
// 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
// 3.2、获取桶
List<StringTerms.Bucket> buckets = agg.getBuckets();
// 3.3、遍历
for (StringTerms.Bucket bucket : buckets) {
// 3.4、获取桶中的key,即品牌名称 3.5、获取桶中的文档数量
System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "台");
// 3.6.获取子聚合结果:
InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");
System.out.println("平均售价:" + avg.getValue());
}
}
/**
* 删除索引
*/
/*@Test
public void deleteIndex() {
mRestTemplate.deleteIndex(ItemEntity.class);
}*/
}
文末顺带科普下es的9200和9300端口
- 9200:使用http请求,所以我们的rest方式的client要使用这个端口进行访问
- 9300:使用tcp请求,是系统预留给es内部组件之间的通信方式