spring data Elasticsearch
1.导入依赖
<dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-data-elasticsearchartifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-testartifactId> <scope>testscope> dependency> dependencies>
2.配置文件,配置elasticsearch的地址
spring: data: elasticsearch: cluster-name: elasticsearch cluster-nodes: 192.168.56.101:9300
3.pojo
@Document(indexName = "item",type = "docs",shards = 1,replicas = 0) public class Item { @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(index = false,type = FieldType.keyword) String images; // 图片地址
4.开启测试类进行测试
@SpringBootTest(classes = DemoApplication.class) @RunWith(SpringRunner.class) public class SearchTest {
创建索引,设置映射
@Test public void createIndex(){ esTemplate.createIndex(Item.class); esTemplate.putMapping(Item.class); }
删除索引库
@Test public void deleteindex(){ esTemplate.deleteIndex("cr7"); }
二.对索引库中的数据增删改查,spring data给我们提供了一个接口,使用时要继承这个接口
public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
这个Long是什么意思?好像跟序列化有关系
1.保存数据
@Test public void index(){ Item item = new Item(1L, "小米手机7", " 手机", "小米", 3499.00, "http://image.leyou.com/13123.jpg"); itemRepository.save(item); }
2.批量保存数据
@Test public void indexList() { 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")); // 接收对象集合,实现批量新增 itemRepository.saveAll(list); }
3.查询全部,并按照价格排序
@Test public void query(){ // 查询全部,并安装价格降序排序 Iterable<Item> items = this.itemRepository.findAll(Sort.by("price").descending()); for (Item item : items) { System.out.println("item = " + item); } }
4.查询一定价格区间
@Test public void queryByPriceBetween(){ List<Item> list = this.itemRepository.findByPriceBetween(2000.00, 3500.00); for (Item item : list) { System.out.println("item = " + item); } }
5.条件查询
@Test public void search(){ // 构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本分词查询 queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米手机")); // 搜索,获取结果 Page<Item> items = this.itemRepository.search(queryBuilder.build()); // 总条数 long total = items.getTotalElements(); System.out.println("total = " + total); for (Item item : items) { System.out.println(item); } }
6.分页查询
/** * 分页查询 */ @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<Item> items = this.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()); for (Item item : items) { System.out.println(item); } }
7.根据分词查询,根据价格排序
@Test public void searchAndSort(){ // 构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本分词查询 queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机")); // 排序 queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC)); // 搜索,获取结果 Page<Item> items = this.itemRepository.search(queryBuilder.build()); // 总条数 long total = items.getTotalElements(); System.out.println("总条数 = " + total); for (Item item : items) { System.out.println(item); } }
8.聚合为桶,根据品牌进行分桶
/** * 聚合为桶 */ @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<Item> aggPage = (AggregatedPage<Item>) 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,即品牌名称 System.out.println(bucket.getKeyAsString()); // 3.5、获取桶中的文档数量 System.out.println(bucket.getDocCount()); } }
9.嵌套聚合,求平均值
/** * 嵌套聚合,求平均值 */ @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<Item> aggPage = (AggregatedPage<Item>) 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()); } }